unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: "Dr. Arne Babenhauserheide" <arne_bab@web.de>
To: "Dr. Arne Babenhauserheide" <arne_bab@web.de>
Cc: "Maxime Devos" <maximedevos@telenet.be>,
	"Ludovic Courtès" <ludo@gnu.org>,
	guile-devel@gnu.org
Subject: Re: [PATCH] add SRFI-119 / language/wisp to Guile? (new patch, squashed)
Date: Mon, 14 Aug 2023 22:30:18 +0200	[thread overview]
Message-ID: <871qg58ikx.fsf@web.de> (raw)
In-Reply-To: <875y5h8j04.fsf@web.de>

[-- Attachment #1: Type: text/plain, Size: 132490 bytes --]


"Dr. Arne Babenhauserheide" <arne_bab@web.de> writes:

> Attached is a new squashed patch. I’ll send another email with only the
> commits for the individual changes on top of the original squashed patch
> to avoid tripping up tools that extract diffs.

This is the promised email with just the changes compared to the
original squashed patch :-)

I tried to create atomic changes, but the indentation change mixed a few
together that I did not manage to separate (I did that indentation
change too early and didn’t commit in time — I’m sorry for that).

To minimize the impact I added a last change including just a diff
without whitespace changes (-w). It starts with DIFF_WITHOUT_WHITESPACE

I hope this simplifies reviewing for you!

Best wishes,
Arne




From ec1d873871040a7bf99cc8f0ab940e09fd76977b Mon Sep 17 00:00:00 2001
From: Arne Babenhauserheide <arne_bab@web.de>
Date: Mon, 12 Jun 2023 01:22:56 +0200
Subject: [PATCH 02/11] SRFI-119: add new files to Makefile.am and bootstrap.am

* am/bootstrap.am (SOURCES): add language/wisp.scm and language/wisp/spec.scm
* test-suite/Makefile.am (SCM_TESTS) add tests/srfi-119.test
---
 am/bootstrap.am        | 3 +++
 test-suite/Makefile.am | 3 ++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/am/bootstrap.am b/am/bootstrap.am
index ff0d1799e..80a8dcdde 100644
--- a/am/bootstrap.am
+++ b/am/bootstrap.am
@@ -393,6 +393,9 @@ SOURCES =					\
 						\
   system/syntax.scm				\
 						\
+  language/wisp.scm				\
+  language/wisp/spec.scm			\
+						\
   system/xref.scm				\
 						\
   sxml/apply-templates.scm			\
diff --git a/test-suite/Makefile.am b/test-suite/Makefile.am
index 81e63bce2..247d97746 100644
--- a/test-suite/Makefile.am
+++ b/test-suite/Makefile.am
@@ -162,7 +162,8 @@ SCM_TESTS = tests/00-initial-env.test		\
 	    tests/srfi-98.test			\
 	    tests/srfi-105.test			\
 	    tests/srfi-111.test			\
-            tests/srfi-171.test                 \
+	    tests/srfi-119.test			\
+	    tests/srfi-171.test			\
 	    tests/srfi-4.test			\
 	    tests/srfi-9.test			\
 	    tests/statprof.test			\
-- 
2.41.0

From c07a1643ca4df87a552abd32cc00d80741ef8e17 Mon Sep 17 00:00:00 2001
From: Arne Babenhauserheide <arne_bab@web.de>
Date: Thu, 10 Aug 2023 08:32:17 +0200
Subject: [PATCH 03/11] SRFI-119: change license of language/wisp/spec to
 LGPLv3+

* module/language/wisp/spec.scm: changed license. This was changed from
  LGPLv3+ to MIT for inclusion in SRFI-119 and was now reverted back to
  LGPLv3+. Permission granted by Maxime Devos who had done changes in
  the MIT version.
---
 module/language/wisp/spec.scm | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/module/language/wisp/spec.scm b/module/language/wisp/spec.scm
index 477036c71..821033432 100644
--- a/module/language/wisp/spec.scm
+++ b/module/language/wisp/spec.scm
@@ -6,25 +6,20 @@
 ;;; Copyright (C) 2014--2023 Arne Babenhauserheide.
 ;;; Copyright (C) 2023 Maxime Devos <maximedevos@telenet.be>
 
-;;; Permission is hereby granted, free of charge, to any person
-;;; obtaining a copy of this software and associated documentation
-;;; files (the "Software"), to deal in the Software without
-;;; restriction, including without limitation the rights to use, copy,
-;;; modify, merge, publish, distribute, sublicense, and/or sell copies
-;;; of the Software, and to permit persons to whom the Software is
-;;; furnished to do so, subject to the following conditions:
-;;;
-;;; The above copyright notice and this permission notice shall be
-;;; included in all copies or substantial portions of the Software.
-;;;
-;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-;;; BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-;;; ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-;;; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-;;; SOFTWARE.
+;;;; This library is free software; you can redistribute it and/or
+;;;; modify it under the terms of the GNU Lesser General Public
+;;;; License as published by the Free Software Foundation; either
+;;;; version 3 of the License, or (at your option) any later version.
+;;;;
+;;;; This library is distributed in the hope that it will be useful,
+;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;;; Lesser General Public License for more details.
+;;;;
+;;;; You should have received a copy of the GNU Lesser General Public
+;;;; License along with this library; if not, write to the Free Software
+;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
 
 ; adapted from spec.scm: https://gitorious.org/nacre/guile-sweet/source/ae306867e371cb4b56e00bb60a50d9a0b8353109:sweet/spec.scm
 (define-module (language wisp spec)
-- 
2.41.0

From 76bd2f42d3a568453981ce8f60f6b06bfc23ccf5 Mon Sep 17 00:00:00 2001
From: Arne Babenhauserheide <arne_bab@web.de>
Date: Sat, 12 Aug 2023 22:06:50 +0200
Subject: [PATCH 04/11] Polish srfi-119 documentation

* doc/ref/srfi-modules.texi (srfi-119): fix capitalization, improve
  wording, and use two spaces after period for navigation in Emacs.
---
 doc/ref/srfi-modules.texi | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/doc/ref/srfi-modules.texi b/doc/ref/srfi-modules.texi
index e9e64bea8..5b82f8070 100644
--- a/doc/ref/srfi-modules.texi
+++ b/doc/ref/srfi-modules.texi
@@ -64,7 +64,7 @@ get the relevant SRFI documents from the SRFI home page
 * SRFI-98::                     Accessing environment variables.
 * SRFI-105::                    Curly-infix expressions.
 * SRFI-111::                    Boxes.
-* SRFI-119::                    Wisp: simpler indentation-sensitive scheme.
+* SRFI-119::                    Wisp: simpler indentation-sensitive Scheme.
 * SRFI-171::                    Transducers
 @end menu
 
@@ -5664,13 +5664,14 @@ Set the contents of @var{box} to @var{value}.
 @end deffn
 
 @node SRFI-119
-@subsection SRFI-119 Wisp: simpler indentation-sensitive scheme.
+@subsection SRFI-119 Wisp: simpler indentation-sensitive Scheme.
 @cindex SRFI-119
 @cindex wisp
 
-The languages shipped in Guile include SRFI-119 (wisp), an encoding of
-Scheme that allows replacing parentheses with equivalent indentation and
-inline colons. See
+The languages shipped in Guile include SRFI-119, also referred to as
+@dfn{Wisp} (for ``Whitespace to Lisp''), an encoding of Scheme that
+allows replacing parentheses with equivalent indentation and inline
+colons.  See
 @uref{http://srfi.schemers.org/srfi-119/srfi-119.html, the specification
 of SRFI-119}.  Some examples:
 
-- 
2.41.0

From 3cc2679d3e2f11c67d52d9c54e8ec66030697006 Mon Sep 17 00:00:00 2001
From: Arne Babenhauserheide <arne_bab@web.de>
Date: Sat, 12 Aug 2023 22:08:54 +0200
Subject: [PATCH 05/11] SRFI-119 spec: fix leading comments

* module/language/wisp/spec.scm (comments): fix capitalization, improve
  wording, and use two spaces after period for navigation in Emacs.
---
 module/language/wisp/spec.scm | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/module/language/wisp/spec.scm b/module/language/wisp/spec.scm
index 821033432..fde08b429 100644
--- a/module/language/wisp/spec.scm
+++ b/module/language/wisp/spec.scm
@@ -1,10 +1,8 @@
-;; Language interface for Wisp in Guile
+;;; Language interface for Wisp in Guile
 
-;;; adapted from guile-sweet: https://gitorious.org/nacre/guile-sweet/source/ae306867e371cb4b56e00bb60a50d9a0b8353109:sweet/common.scm
-
-;;; Copyright (C) 2005--2014 by David A. Wheeler and Alan Manuel K. Gloria
-;;; Copyright (C) 2014--2023 Arne Babenhauserheide.
-;;; Copyright (C) 2023 Maxime Devos <maximedevos@telenet.be>
+;; Copyright (C) 2005--2014 by David A. Wheeler and Alan Manuel K. Gloria
+;; Copyright (C) 2014--2023 Arne Babenhauserheide.
+;; Copyright (C) 2023 Maxime Devos <maximedevos@telenet.be>
 
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -20,8 +18,8 @@
 ;;;; License along with this library; if not, write to the Free Software
 ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
+;; adapted from spec.scm: https://gitorious.org/nacre/guile-sweet/?p=nacre:guile-sweet.git;a=blob;f=sweet/spec.scm;hb=ae306867e371cb4b56e00bb60a50d9a0b8353109
 
-; adapted from spec.scm: https://gitorious.org/nacre/guile-sweet/source/ae306867e371cb4b56e00bb60a50d9a0b8353109:sweet/spec.scm
 (define-module (language wisp spec)
   #:use-module (language wisp)
   #:use-module (system base compile)
-- 
2.41.0

From 8c88bdea77ba33ced9e449165c6ad939f3f8c388 Mon Sep 17 00:00:00 2001
From: Arne Babenhauserheide <arne_bab@web.de>
Date: Sat, 12 Aug 2023 22:10:03 +0200
Subject: [PATCH 06/11] SRFI-119 (wisp): review fixes

* module/language/wisp.scm (comments): use ;; for all non-margin
  comments
* module/language/wisp.scm (indentation): auto-indent cleanly
* module/language/wisp.scm (indent-level-reduction, indent-level-reduction,
    wisp-scheme-indentation-to-parens, wisp-make-improper): use raise-exception
  instead of raw throw
* module/language/wisp.scm (wisp-scheme-read-chunk-lines): use conventional
  variable naming in-indent? instead of inindent, also
  in-underscoreindent? in-comment?
* module/language/wisp.scm (top-level): guard read-enable curly-infix
  with eval-when
* module/language/wisp.scm (make-line): new function, alias of list.
  Change: used as apply make-line indent code (instead of append)
---
 module/language/wisp.scm | 1225 +++++++++++++++++++-------------------
 1 file changed, 604 insertions(+), 621 deletions(-)

diff --git a/module/language/wisp.scm b/module/language/wisp.scm
index 7a12e126a..acc1f0725 100644
--- a/module/language/wisp.scm
+++ b/module/language/wisp.scm
@@ -31,643 +31,627 @@
 ;;; Code:
 
 (define-module (language wisp)
-   #:export (wisp-scheme-read-chunk wisp-scheme-read-all 
-               wisp-scheme-read-file-chunk wisp-scheme-read-file
-               wisp-scheme-read-string))
+  #:export (wisp-scheme-read-chunk wisp-scheme-read-all
+                                   wisp-scheme-read-file-chunk wisp-scheme-read-file
+                                   wisp-scheme-read-string)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-11); for let-values
+  #:use-module (srfi srfi-9); for records
+  #:use-module (ice-9 rw); for write-string/partial
+  #:use-module (ice-9 match))
 
-; use curly-infix by default
-(read-enable 'curly-infix)
-
-(use-modules
-  (srfi srfi-1)
-  (srfi srfi-11); for let-values
-  (ice-9 rw); for write-string/partial
-  (ice-9 match))
+;; use curly-infix by default
+(eval-when (expand load eval)
+  (read-enable 'curly-infix))
 
 
 ;; Helper functions for the indent-and-symbols data structure: '((indent token token ...) ...)
+(define make-line list)
+
 (define (line-indent line)
-         (car line))
+  (car line))
 
 (define (line-real-indent line)
-         "Get the indentation without the comment-marker for unindented lines (-1 is treated as 0)."
-         (let (( indent (line-indent line)))
-             (if (= -1 indent)
-               0
-               indent)))
+  "Get the indentation without the comment-marker for unindented lines (-1 is treated as 0)."
+  (let ((indent (line-indent line)))
+    (if (= -1 indent)
+        0
+        indent)))
 
 (define (line-code line)
-         (let ((code (cdr line)))
-             ; propagate source properties
-             (when (not (null? code))
-                    (set-source-properties! code (source-properties line)))
-             code))
+  "Strip the indentation markers from the beginning of the line and preserve source-properties"
+  (let ((code (cdr line)))
+    ;; propagate source properties
+    (when (not (null? code))
+      (set-source-properties! code (source-properties line)))
+    code))
 
-; literal values I need
-(define readcolon 
-       (string->symbol ":"))
+;; literal values I need
+(define readcolon
+  (string->symbol ":"))
 
 (define wisp-uuid "e749c73d-c826-47e2-a798-c16c13cb89dd")
-; define an intermediate dot replacement with UUID to avoid clashes.
+;; define an intermediate dot replacement with UUID to avoid clashes.
 (define repr-dot ; .
-       (string->symbol (string-append "REPR-DOT-" wisp-uuid)))
+  (string->symbol (string-append "REPR-DOT-" wisp-uuid)))
 
-; allow using reader additions as the first element on a line to prefix the list
+;; allow using reader additions as the first element on a line to prefix the list
 (define repr-quote ; '
-       (string->symbol (string-append "REPR-QUOTE-" wisp-uuid)))
+  (string->symbol (string-append "REPR-QUOTE-" wisp-uuid)))
 (define repr-unquote ; ,
-       (string->symbol (string-append "REPR-UNQUOTE-" wisp-uuid)))
+  (string->symbol (string-append "REPR-UNQUOTE-" wisp-uuid)))
 (define repr-quasiquote ; `
-       (string->symbol (string-append "REPR-QUASIQUOTE-" wisp-uuid)))
+  (string->symbol (string-append "REPR-QUASIQUOTE-" wisp-uuid)))
 (define repr-unquote-splicing ; ,@
-       (string->symbol (string-append "REPR-UNQUOTESPLICING-" wisp-uuid)))
+  (string->symbol (string-append "REPR-UNQUOTESPLICING-" wisp-uuid)))
 
 (define repr-syntax ; #'
-       (string->symbol (string-append "REPR-SYNTAX-" wisp-uuid)))
+  (string->symbol (string-append "REPR-SYNTAX-" wisp-uuid)))
 (define repr-unsyntax ; #,
-       (string->symbol (string-append "REPR-UNSYNTAX-" wisp-uuid)))
+  (string->symbol (string-append "REPR-UNSYNTAX-" wisp-uuid)))
 (define repr-quasisyntax ; #`
-       (string->symbol (string-append "REPR-QUASISYNTAX-" wisp-uuid)))
+  (string->symbol (string-append "REPR-QUASISYNTAX-" wisp-uuid)))
 (define repr-unsyntax-splicing ; #,@
-       (string->symbol (string-append "REPR-UNSYNTAXSPLICING-" wisp-uuid)))
+  (string->symbol (string-append "REPR-UNSYNTAXSPLICING-" wisp-uuid)))
 
-; TODO: wrap the reader to return the repr of the syntax reader
-; additions
+;; TODO: wrap the reader to return the repr of the syntax reader
+;; additions
 
 (define (match-charlist-to-repr charlist)
-         (let
-           ((chlist (reverse charlist)))
-           (cond
-             ((equal? chlist (list #\.))
-               repr-dot)
-             ((equal? chlist (list #\'))
-               repr-quote)
-             ((equal? chlist (list #\,))
-               repr-unquote)
-             ((equal? chlist (list #\`))
-               repr-quasiquote)
-             ((equal? chlist (list #\, #\@))
-               repr-unquote-splicing)
-             ((equal? chlist (list #\# #\'))
-               repr-syntax)
-             ((equal? chlist (list #\# #\,))
-               repr-unsyntax)
-             ((equal? chlist (list #\# #\`))
-               repr-quasisyntax)
-             ((equal? chlist (list #\# #\, #\@))
-               repr-unsyntax-splicing)
-             (else
-               #f))))
+  (let
+      ((chlist (reverse charlist)))
+    (cond
+     ((equal? chlist (list #\.))
+      repr-dot)
+     ((equal? chlist (list #\'))
+      repr-quote)
+     ((equal? chlist (list #\,))
+      repr-unquote)
+     ((equal? chlist (list #\`))
+      repr-quasiquote)
+     ((equal? chlist (list #\, #\@))
+      repr-unquote-splicing)
+     ((equal? chlist (list #\# #\'))
+      repr-syntax)
+     ((equal? chlist (list #\# #\,))
+      repr-unsyntax)
+     ((equal? chlist (list #\# #\`))
+      repr-quasisyntax)
+     ((equal? chlist (list #\# #\, #\@))
+      repr-unsyntax-splicing)
+     (else
+      #f))))
 
 (define (wisp-read port)
-       "wrap read to catch list prefixes."
-       (let ((prefix-maxlen 4))
-         (let longpeek
-           ((peeked '())
-            (repr-symbol #f))
-           (cond
-             ((or (< prefix-maxlen (length peeked)) (eof-object? (peek-char port)) (equal? #\space (peek-char port)) (equal? #\newline (peek-char port)))
-               (if repr-symbol ; found a special symbol, return it.
-                  repr-symbol
-                  (let unpeek
-                    ((remaining peeked))
-                    (cond
-                      ((equal? '() remaining)
-                        (read port)); let read to the work
-                      (else
-                        (unread-char (car remaining) port)
-                        (unpeek (cdr remaining)))))))
-             (else
-               (let*
-                 ((next-char (read-char port))
-                  (peeked (cons next-char peeked)))
-                 (longpeek
-                   peeked
-                   (match-charlist-to-repr peeked))))))))
+  "wrap read to catch list prefixes."
+  (let ((prefix-maxlen 4))
+    (let longpeek
+        ((peeked '())
+         (repr-symbol #f))
+      (cond
+       ((or (< prefix-maxlen (length peeked)) (eof-object? (peek-char port)) (equal? #\space (peek-char port)) (equal? #\newline (peek-char port)))
+        (if repr-symbol ; found a special symbol, return it.
+            repr-symbol
+            (let unpeek
+                ((remaining peeked))
+              (cond
+               ((equal? '() remaining)
+                (read port)); let read to the work
+               (else
+                (unread-char (car remaining) port)
+                (unpeek (cdr remaining)))))))
+       (else
+        (let*
+            ((next-char (read-char port))
+             (peeked (cons next-char peeked)))
+          (longpeek
+           peeked
+           (match-charlist-to-repr peeked))))))))
 
 
 
 (define (line-continues? line)
-         (equal? repr-dot (car (line-code line))))
+  (equal? repr-dot (car (line-code line))))
 
 (define (line-only-colon? line)
-         (and
-           (equal? ":" (car (line-code line)))
-           (null? (cdr (line-code line)))))
+  (and
+   (equal? ":" (car (line-code line)))
+   (null? (cdr (line-code line)))))
 
 (define (line-empty-code? line)
-         (null? (line-code line)))
+  (null? (line-code line)))
 
 (define (line-empty? line)
-         (and
-           ; if indent is -1, we stripped a comment, so the line was not really empty.
-           (= 0 (line-indent line))
-           (line-empty-code? line)))
+  (and
+   ;; if indent is -1, we stripped a comment, so the line was not really empty.
+   (= 0 (line-indent line))
+   (line-empty-code? line)))
 
 (define (line-strip-continuation line)
-         (if (line-continues? line)
-              (append
-                (list
-                  (line-indent line))
-                (cdr (line-code line)))
-              line))
+  (if (line-continues? line)
+      (apply make-line
+       (line-indent line)
+       (cdr (line-code line)))
+      line))
 
 (define (line-strip-indentation-marker line)
-         "Strip the indentation markers from the beginning of the line"
-         (cdr line))
+  "Strip the indentation markers from the beginning of the line for line-finalize without propagating source-properties (those are propagated in a second step)"
+  (cdr line))
 
 (define (indent-level-reduction indentation-levels level select-fun)
-         "Reduce the INDENTATION-LEVELS to the given LEVEL and return the value selected by SELECT-FUN"
-         (let loop
-           ((newlevels indentation-levels)
-             (diff 0))
-           (cond
-             ((= level (car newlevels))
-               (select-fun (list diff indentation-levels)))
-             ((< level (car newlevels))
-               (loop
-                 (cdr newlevels)
-                 (1+ diff)))
-             (else
-               (throw 'wisp-syntax-error "Level ~A not found in the indentation-levels ~A.")))))
+  "Reduce the INDENTATION-LEVELS to the given LEVEL and return the value selected by SELECT-FUN"
+  (let loop
+      ((newlevels indentation-levels)
+       (diff 0))
+    (cond
+     ((= level (car newlevels))
+      (select-fun (list diff indentation-levels)))
+     ((< level (car newlevels))
+      (loop
+       (cdr newlevels)
+       (1+ diff)))
+     (else
+      (raise-exception (make-exception-from-throw 'wisp-syntax-error (list (format #f "Level ~A not found in the indentation-levels ~A." level indentation-levels))))))))
 
 (define (indent-level-difference indentation-levels level)
-         "Find how many indentation levels need to be popped off to find the given level."
-         (indent-level-reduction indentation-levels level
-           (lambda (x); get the count
-                    (car x))))
+  "Find how many indentation levels need to be popped off to find the given level."
+  (indent-level-reduction indentation-levels level
+                          (lambda (x); get the count
+                            (car x))))
 
 (define (indent-reduce-to-level indentation-levels level)
-         "Find how many indentation levels need to be popped off to find the given level."
-         (indent-level-reduction indentation-levels level
-           (lambda (x); get the levels
-                    (car (cdr x)))))
+  "Find how many indentation levels need to be popped off to find the given level."
+  (indent-level-reduction indentation-levels level
+                          (lambda (x); get the levels
+                            (car (cdr x)))))
 
 (define (chunk-ends-with-period currentsymbols next-char)
-       "Check whether indent-and-symbols ends with a period, indicating the end of a chunk."
-       (and (not (null? currentsymbols))
-             (equal? #\newline next-char)
-             (equal? repr-dot
-                    (list-ref currentsymbols (- (length currentsymbols) 1)))))
+  "Check whether indent-and-symbols ends with a period, indicating the end of a chunk."
+  (and (not (null? currentsymbols))
+       (equal? #\newline next-char)
+       (equal? repr-dot
+               (list-ref currentsymbols (- (length currentsymbols) 1)))))
+
 
 (define (wisp-scheme-read-chunk-lines port)
-         (let loop
-           ((indent-and-symbols (list)); '((5 "(foobar)" "\"yobble\"")(3 "#t"))
-             (inindent #t)
-             (inunderscoreindent (equal? #\_ (peek-char port)))
-             (incomment #f)
-             (currentindent 0)
-             (currentsymbols '())
-             (emptylines 0))
-           (cond
-            ((>= emptylines 2); the chunk end has to be checked
-                              ; before we look for new chars in the
-                              ; port to make execution in the REPL
-                              ; after two empty lines work
-                              ; (otherwise it shows one more line).
-             indent-and-symbols)
-            (else
-             (let ((next-char (peek-char port)))
-               (cond
-                 ((eof-object? next-char)
-                   (append indent-and-symbols (list (append (list currentindent) currentsymbols))))
-                 ((and inindent (zero? currentindent) (not incomment) (not (null? indent-and-symbols)) (not inunderscoreindent) (not (or (equal? #\space next-char) (equal? #\newline next-char) (equal? (string-ref ";" 0) next-char))))
-                  (append indent-and-symbols)); top-level form ends chunk
-                 ((chunk-ends-with-period currentsymbols next-char)
-                   ; the line ends with a period. This is forbidden in
-                   ; SRFI-119. Use it to end the line in the REPL without
-                   ; showing continuation dots (...).
-                   (append indent-and-symbols (list (append (list currentindent) (drop-right currentsymbols 1)))))
-                 ((and inindent (equal? #\space next-char))
-                   (read-char port); remove char
-                   (loop
-                     indent-and-symbols
-                     #t ; inindent
-                     #f ; inunderscoreindent
-                     #f ; incomment
-                     (1+ currentindent)
-                     currentsymbols
-                     emptylines))
-                 ((and inunderscoreindent (equal? #\_ next-char))
-                   (read-char port); remove char
-                   (loop
-                     indent-and-symbols
-                     #t ; inindent
-                     #t ; inunderscoreindent
-                     #f ; incomment
-                     (1+ currentindent)
-                     currentsymbols
-                     emptylines))
-                 ; any char but whitespace *after* underscoreindent is
-                 ; an error. This is stricter than the current wisp
-                 ; syntax definition. TODO: Fix the definition. Better
-                 ; start too strict. FIXME: breaks on lines with only
-                 ; underscores which should be empty lines.
-                 ((and inunderscoreindent (and (not (equal? #\space next-char)) (not (equal? #\newline next-char))))
-                   (throw 'wisp-syntax-error "initial underscores without following whitespace at beginning of the line after" (last indent-and-symbols)))
-                 ((equal? #\newline next-char)
-                   (read-char port); remove the newline
-                   ; The following two lines would break the REPL by requiring one char too many.
-                   ; if : and (equal? #\newline next-char) : equal? #\return : peek-char port
-                   ;      read-char port ; remove a full \n\r. Damn special cases...
-                   (let* ; distinguish pure whitespace lines and lines
-                        ; with comment by giving the former zero
-                        ; indent. Lines with a comment at zero indent
-                        ; get indent -1 for the same reason - meaning
-                        ; not actually empty.
-                     ((indent
-                         (cond
-                           (incomment
-                             (if (= 0 currentindent); specialcase
-                               -1
-                               currentindent))
-                           ((not (null? currentsymbols)); pure whitespace
-                             currentindent)
-                           (else
-                             0)))
-                       (parsedline (append (list indent) currentsymbols))
-                       (emptylines
-                         (if (not (line-empty? parsedline))
-                            0 
-                            (1+ emptylines))))
-                     (when (not (= 0 (length parsedline)))
-                         ; set the source properties to parsedline so we can try to add them later.
-                         (set-source-property! parsedline 'filename (port-filename port))
-                         (set-source-property! parsedline 'line (port-line port)))
-                     ; TODO: If the line is empty. Either do it here and do not add it, just
-                     ; increment the empty line counter, or strip it later. Replace indent
-                     ; -1 by indent 0 afterwards.
-                     (loop
-                       (append indent-and-symbols (list parsedline))
-                       #t ; inindent
-                       (if (<= 2 emptylines)
-                         #f ; chunk ends here
-                         (equal? #\_ (peek-char port))); are we in underscore indent?
-                       #f ; incomment
-                       0
-                       '()
-                       emptylines)))
-                 ((equal? #t incomment)
-                   (read-char port); remove one comment character
-                   (loop
-                     indent-and-symbols
-                     #f ; inindent 
-                     #f ; inunderscoreindent 
-                     #t ; incomment
-                     currentindent
-                     currentsymbols
-                     emptylines))
-                 ((or (equal? #\space next-char) (equal? #\tab next-char) (equal? #\return next-char)); remove whitespace when not in indent
-                   (read-char port); remove char
-                   (loop
-                     indent-and-symbols
-                     #f ; inindent
-                     #f ; inunderscoreindent
-                     #f ; incomment
-                     currentindent
-                     currentsymbols
-                     emptylines))
-                          ; | cludge to appease the former wisp parser
-                          ; | used for bootstrapping which has a
-                          ; v problem with the literal comment char
-                 ((equal? (string-ref ";" 0) next-char)
-                   (loop
-                     indent-and-symbols
-                     #f ; inindent
-                     #f ; inunderscoreindent
-                     #t ; incomment
-                     currentindent
-                     currentsymbols
-                     emptylines))
-                 (else ; use the reader
-                   (loop
-                     indent-and-symbols
-                     #f ; inindent
-                     #f ; inunderscoreindent
-                     #f ; incomment
-                     currentindent
-                     ; this also takes care of the hashbang and leading comments.
-                     (append currentsymbols (list (wisp-read port)))
-                     emptylines))))))))
+  (let loop
+      ((indent-and-symbols (list)); '((5 "(foobar)" "\"yobble\"")(3 "#t"))
+       (in-indent? #t)
+       (in-underscoreindent? (equal? #\_ (peek-char port)))
+       (in-comment? #f)
+       (currentindent 0)
+       (currentsymbols '())
+       (emptylines 0))
+    (cond
+     ((>= emptylines 2)
+      ;; the chunk end has to be checked
+      ;; before we look for new chars in the
+      ;; port to make execution in the REPL
+      ;; after two empty lines work
+      ;; (otherwise it shows one more line).
+      indent-and-symbols)
+     (else
+      (let ((next-char (peek-char port)))
+        (cond
+         ((eof-object? next-char)
+          (append indent-and-symbols (list (apply make-line currentindent currentsymbols))))
+         ((and in-indent? (zero? currentindent) (not in-comment?) (not (null? indent-and-symbols)) (not in-underscoreindent?) (not (or (equal? #\space next-char) (equal? #\newline next-char) (equal? (string-ref ";" 0) next-char))))
+          (append indent-and-symbols)); top-level form ends chunk
+         ((chunk-ends-with-period currentsymbols next-char)
+          ;; the line ends with a period. This is forbidden in
+          ;; SRFI-119. Use it to end the line in the REPL without
+          ;; showing continuation dots (...).
+          (append indent-and-symbols (list (apply make-line currentindent (drop-right currentsymbols 1)))))
+         ((and in-indent? (equal? #\space next-char))
+          (read-char port); remove char
+          (loop
+           indent-and-symbols
+           #t ; in-indent?
+           #f ; in-underscoreindent?
+           #f ; in-comment?
+           (1+ currentindent)
+           currentsymbols
+           emptylines))
+         ((and in-underscoreindent? (equal? #\_ next-char))
+          (read-char port); remove char
+          (loop
+           indent-and-symbols
+           #t ; in-indent?
+           #t ; in-underscoreindent?
+           #f ; in-comment?
+           (1+ currentindent)
+           currentsymbols
+           emptylines))
+         ;; any char but whitespace *after* underscoreindent is
+         ;; an error. This is stricter than the current wisp
+         ;; syntax definition. TODO: Fix the definition. Better
+         ;; start too strict. FIXME: breaks on lines with only
+         ;; underscores which should be empty lines.
+         ((and in-underscoreindent? (and (not (equal? #\space next-char)) (not (equal? #\newline next-char))))
+          (raise-exception (make-exception-from-throw 'wisp-syntax-error (list "initial underscores without following whitespace at beginning of the line after" (last indent-and-symbols)))))
+         ((equal? #\newline next-char)
+          (read-char port); remove the newline
+          (let*
+              ;; distinguish pure whitespace lines and lines
+              ;; with comment by giving the former zero
+              ;; indent. Lines with a comment at zero indent
+              ;; get indent -1 for the same reason - meaning
+              ;; not actually empty.
+              ((indent
+                (cond
+                 (in-comment?
+                  (if (= 0 currentindent); specialcase
+                      -1
+                      currentindent))
+                 ((not (null? currentsymbols)); pure whitespace
+                  currentindent)
+                 (else
+                  0)))
+               (parsedline (apply make-line indent currentsymbols))
+               (emptylines
+                (if (not (line-empty? parsedline))
+                    0
+                    (1+ emptylines))))
+            (when (not (= 0 (length (line-code parsedline))))
+              ;; set the source properties to parsedline so we can try to add them later.
+              (set-source-property! parsedline 'filename (port-filename port))
+              (set-source-property! parsedline 'line (port-line port)))
+            ;; TODO: If the line is empty. Either do it here and do not add it, just
+            ;; increment the empty line counter, or strip it later. Replace indent
+            ;; -1 by indent 0 afterwards.
+            (loop
+             (append indent-and-symbols (list parsedline))
+             #t ; in-indent?
+             (if (<= 2 emptylines)
+                 #f ; chunk ends here
+                 (equal? #\_ (peek-char port))); are we in underscore indent?
+             #f ; in-comment?
+             0
+             '()
+             emptylines)))
+         ((equal? #t in-comment?)
+          (read-char port); remove one comment character
+          (loop
+           indent-and-symbols
+           #f ; in-indent?
+           #f ; in-underscoreindent?
+           #t ; in-comment?
+           currentindent
+           currentsymbols
+           emptylines))
+         ((or (equal? #\space next-char) (equal? #\tab next-char) (equal? #\return next-char)); remove whitespace when not in indent
+          (read-char port); remove char
+          (loop
+           indent-and-symbols
+           #f ; in-indent?
+           #f ; in-underscoreindent?
+           #f ; in-comment?
+           currentindent
+           currentsymbols
+           emptylines))
+         ;; | cludge to appease the former wisp parser
+         ;; | used for bootstrapping which has a
+         ;; v problem with the literal comment char
+         ((equal? (string-ref ";" 0) next-char)
+          (loop
+           indent-and-symbols
+           #f ; in-indent?
+           #f ; in-underscoreindent?
+           #t ; in-comment?
+           currentindent
+           currentsymbols
+           emptylines))
+         (else ; use the reader
+          (loop
+           indent-and-symbols
+           #f ; in-indent?
+           #f ; in-underscoreindent?
+           #f ; in-comment?
+           currentindent
+           ;; this also takes care of the hashbang and leading comments.
+           (append currentsymbols (list (wisp-read port)))
+           emptylines))))))))
 
 
 (define (line-code-replace-inline-colons line)
-         "Replace inline colons by opening parens which close at the end of the line"
-         ; format #t "replace inline colons for line ~A\n" line
-         (let loop
-           ((processed '())
-              (unprocessed line))
-           (cond
-             ((null? unprocessed)
-               ; format #t "inline-colons processed line: ~A\n" processed
-               processed)
-             ; replace : . with nothing
-             ((and (<= 2 (length unprocessed)) (equal? readcolon (car unprocessed)) (equal? repr-dot (car (cdr unprocessed))))
-               (loop
-                 (append processed
-                   (loop '() (cdr (cdr unprocessed))))
-                 '()))
-             ((equal? readcolon (car unprocessed))
-               (loop
-                 ; FIXME: This should turn unprocessed into a list. 
-                 (append processed
-                   (list (loop '() (cdr unprocessed))))
-                 '()))
-             (else
-               (loop
-                 (append processed
-                   (list (car unprocessed)))
-                 (cdr unprocessed))))))
+  "Replace inline colons by opening parens which close at the end of the line"
+  ;; format #t "replace inline colons for line ~A\n" line
+  (let loop
+      ((processed '())
+       (unprocessed line))
+    (cond
+     ((null? unprocessed)
+      ;; format #t "inline-colons processed line: ~A\n" processed
+      processed)
+     ;; replace : . with nothing
+     ((and (<= 2 (length unprocessed)) (equal? readcolon (car unprocessed)) (equal? repr-dot (car (cdr unprocessed))))
+      (loop
+       (append processed
+               (loop '() (cdr (cdr unprocessed))))
+       '()))
+     ((equal? readcolon (car unprocessed))
+      (loop
+       (append processed
+               (list (loop '() (cdr unprocessed))))
+       '()))
+     (else
+      (loop
+       (append processed
+               (list (car unprocessed)))
+       (cdr unprocessed))))))
 
 (define (line-replace-inline-colons line)
-         (cons
-           (line-indent line)
-           (line-code-replace-inline-colons (line-code line))))
+  (cons
+   (line-indent line)
+   (line-code-replace-inline-colons (line-code line))))
 
 (define (line-strip-lone-colon line)
-         "A line consisting only of a colon is just a marked indentation level. We need to kill the colon before replacing inline colons."
-         (if
-           (equal?
-             (line-code line)
-             (list readcolon))
-           (list (line-indent line))
-           line))
+  "A line consisting only of a colon is just a marked indentation level. We need to kill the colon before replacing inline colons."
+  (if (equal? (line-code line) (list readcolon))
+      (make-line (line-indent line))
+      line))
 
 (define (line-finalize line)
-       "Process all wisp-specific information in a line and strip it"
-       (let ((l (line-code-replace-inline-colons
-               (line-strip-indentation-marker
-                 (line-strip-lone-colon
-                   (line-strip-continuation line))))))
-         (when (not (null? (source-properties line)))
-                (catch #t
-                  (lambda ()
-                    (set-source-properties! l (source-properties line)))
-                  (lambda (key . arguments)
-                    #f)))
-         l))
+  "Process all wisp-specific information in a line and strip it"
+  (let ((l (line-code-replace-inline-colons
+            (line-strip-indentation-marker
+             (line-strip-lone-colon
+              (line-strip-continuation line))))))
+    (when (not (null? (source-properties line)))
+      (catch #t
+        (lambda ()
+          (set-source-properties! l (source-properties line)))
+        (lambda (key . arguments)
+          #f)))
+    l))
 
 (define (wisp-add-source-properties-from source target)
-       "Copy the source properties from source into the target and return the target."
-       (catch #t
-           (lambda ()
-               (set-source-properties! target (source-properties source)))
-           (lambda (key . arguments)
-               #f))
-       target)
+  "Copy the source properties from source into the target and return the target."
+  (catch #t
+    (lambda ()
+      (set-source-properties! target (source-properties source)))
+    (lambda (key . arguments)
+      #f))
+  target)
 
 (define (wisp-propagate-source-properties code)
-       "Propagate the source properties from the sourrounding list into every part of the code."
-       (let loop
-         ((processed '())
-           (unprocessed code))
-         (cond
-           ((and (null? processed) (not (pair? unprocessed)) (not (list? unprocessed)))
-             unprocessed)
-           ((and (pair? unprocessed) (not (list? unprocessed)))
-             (cons
-               (wisp-propagate-source-properties (car unprocessed))
-               (wisp-propagate-source-properties (cdr unprocessed))))
-           ((null? unprocessed)
-             processed)
-           (else
-             (let ((line (car unprocessed)))
-               (if (null? (source-properties unprocessed))
-                   (wisp-add-source-properties-from line unprocessed)
-                   (wisp-add-source-properties-from unprocessed line))
-               (loop
-                 (append processed (list (wisp-propagate-source-properties line)))
-                 (cdr unprocessed)))))))
+  "Propagate the source properties from the sourrounding list into every part of the code."
+  (let loop
+      ((processed '())
+       (unprocessed code))
+    (cond
+     ((and (null? processed) (not (pair? unprocessed)) (not (list? unprocessed)))
+      unprocessed)
+     ((and (pair? unprocessed) (not (list? unprocessed)))
+      (cons
+       (wisp-propagate-source-properties (car unprocessed))
+       (wisp-propagate-source-properties (cdr unprocessed))))
+     ((null? unprocessed)
+      processed)
+     (else
+      (let ((line (car unprocessed)))
+        (if (null? (source-properties unprocessed))
+            (wisp-add-source-properties-from line unprocessed)
+            (wisp-add-source-properties-from unprocessed line))
+        (loop
+         (append processed (list (wisp-propagate-source-properties line)))
+         (cdr unprocessed)))))))
 
 (define* (wisp-scheme-indentation-to-parens lines)
-         "Add parentheses to lines and remove the indentation markers"
-         (when
-           (and
-             (not (null? lines))
-             (not (line-empty-code? (car lines)))
-             (not (= 0 (line-real-indent (car lines))))); -1 is a line with a comment
-           (if (= 1 (line-real-indent (car lines)))
-             ;; accept a single space as indentation of the first line (and ignore the indentation) to support meta commands
-             (set! lines
-                  (cons
-                      (cons 0 (cdr (car lines)))
-                      (cdr lines)))
-             (throw 'wisp-syntax-error
+  "Add parentheses to lines and remove the indentation markers"
+  (when
+      (and
+       (not (null? lines))
+       (not (line-empty-code? (car lines)))
+       (not (= 0 (line-real-indent (car lines))))); -1 is a line with a comment
+    (if (= 1 (line-real-indent (car lines)))
+        ;; accept a single space as indentation of the first line (and ignore the indentation) to support meta commands
+        (set! lines
+              (cons
+               (cons 0 (cdr (car lines)))
+               (cdr lines)))
+        (raise-exception (make-exception-from-throw 'wisp-syntax-error (list
                (format #f "The first symbol in a chunk must start at zero indentation. Indentation and line: ~A"
-                 (car lines)))))
-         (let loop
-           ((processed '())
-             (unprocessed lines)
-             (indentation-levels '(0)))
-           (let*
-             ((current-line
-                 (if (<= 1 (length unprocessed))
-                      (car unprocessed)
-                      (list 0))); empty code
-               (next-line
-                 (if (<= 2 (length unprocessed))
-                      (car (cdr unprocessed))
-                      (list 0))); empty code
-               (current-indentation
-                      (car indentation-levels))
-               (current-line-indentation (line-real-indent current-line)))
-             ; format #t "processed: ~A\ncurrent-line: ~A\nnext-line: ~A\nunprocessed: ~A\nindentation-levels: ~A\ncurrent-indentation: ~A\n\n"
-             ;     . processed current-line next-line unprocessed indentation-levels current-indentation
-             (cond
-                 ; the real end: this is reported to the outside world.
-               ((and (null? unprocessed) (not (null? indentation-levels)) (null? (cdr indentation-levels)))
-                 ; display "done\n"
-                 ; reverse the processed lines, because I use cons.
-                 processed)
-               ; the recursion end-condition
-               ((and (null? unprocessed))
-                 ; display "last step\n"
-                 ; this is the last step. Nothing more to do except
-                 ; for rolling up the indentation levels.  return the
-                 ; new processed and unprocessed lists: this is a
-                 ; side-recursion
-                 (values processed unprocessed))
-               ((null? indentation-levels)
-                 ; display "indentation-levels null\n"
-                 (throw 'wisp-programming-error "The indentation-levels are null but the current-line is null: Something killed the indentation-levels."))
-               (else ; now we come to the line-comparisons and indentation-counting.
-                   (cond
-                     ((line-empty-code? current-line)
-                       ; display "current-line empty\n"
-                       ; We cannot process indentation without
-                       ; code. Just switch to the next line. This should
-                       ; only happen at the start of the recursion.
-                       ; TODO: Somehow preserve the line-numbers.
-                       (loop
-                         processed
-                         (cdr unprocessed)
-                         indentation-levels))
-                     ((and (line-empty-code? next-line) (<= 2 (length unprocessed)))
-                       ; display "next-line empty\n"
-                       ; TODO: Somehow preserve the line-numbers.
-                       ; take out the next-line from unprocessed.
-                       (loop
-                         processed
-                         (cons current-line
-                           (cdr (cdr unprocessed)))
-                         indentation-levels))
-                     ((> current-indentation current-line-indentation)
-                       ; display "current-indent > next-line\n"
-                       ; this just steps back one level via the side-recursion.
-                       (let ((previous-indentation (car (cdr indentation-levels))))
-                         (if (<= current-line-indentation previous-indentation)
-                            (values processed unprocessed)
-                            (begin ;; not yet used level! TODO: maybe throw an error here instead of a warning.
-                                (let ((linenumber (- (length lines) (length unprocessed))))
-                                    (format (current-error-port) ";;; WARNING:~A: used lower but undefined indentation level (line ~A of the current chunk: ~S). This makes refactoring much more error-prone, therefore it might become an error in a later version of Wisp.\n" (source-property current-line 'line) linenumber (cdr current-line)))
-                                (loop
-                                  processed
-                                  unprocessed
-                                  (cons ; recursion via the indentation-levels
-                                    current-line-indentation
-                                    (cdr indentation-levels)))))))
-                     ((= current-indentation current-line-indentation)
-                       ; display "current-indent = next-line\n"
-                       (let
-                         ((line (line-finalize current-line))
-                           (next-line-indentation (line-real-indent next-line)))
-                         (cond
-                           ((>= current-line-indentation next-line-indentation)
-                             ; simple recursiive step to the next line
-                             ; display "current-line-indent >= next-line-indent\n"
-                             (loop
-                               (append processed
-                                 (if (line-continues? current-line)
-                                      line
-                                      (wisp-add-source-properties-from line (list line))))
-                               (cdr unprocessed); recursion here
-                               indentation-levels))
-                           ((< current-line-indentation next-line-indentation)
-                             ; display "current-line-indent < next-line-indent\n"
-                             ; format #t "line: ~A\n" line
-                             ; side-recursion via a sublist
-                             (let-values
-                               (((sub-processed sub-unprocessed)
-                                   (loop
-                                     line
-                                     (cdr unprocessed); recursion here
-                                     indentation-levels)))
-                               ; format #t "side-recursion:\n  sub-processed: ~A\n  processed: ~A\n\n" sub-processed processed
-                               (loop
-                                 (append processed (list sub-processed))
-                                 sub-unprocessed ; simply use the recursion from the sub-recursion
-                                 indentation-levels))))))
-                     ((< current-indentation current-line-indentation)
-                       ; display "current-indent < next-line\n"
-                       (loop
-                         processed
-                         unprocessed
-                         (cons ; recursion via the indentation-levels
-                           current-line-indentation
-                           indentation-levels)))
-                     (else
-                       (throw 'wisp-not-implemented
-                             (format #f "Need to implement further line comparison: current: ~A, next: ~A, processed: ~A."
-                               current-line next-line processed)))))))))
+                       (car lines)))))))
+  (let loop
+      ((processed '())
+       (unprocessed lines)
+       (indentation-levels '(0)))
+    (let*
+        ((current-line
+          (if (<= 1 (length unprocessed))
+              (car unprocessed)
+              (make-line 0))); empty code
+         (next-line
+          (if (<= 2 (length unprocessed))
+              (car (cdr unprocessed))
+              (make-line 0))); empty code
+         (current-indentation
+          (car indentation-levels))
+         (current-line-indentation (line-real-indent current-line)))
+      ;; format #t "processed: ~A\ncurrent-line: ~A\nnext-line: ~A\nunprocessed: ~A\nindentation-levels: ~A\ncurrent-indentation: ~A\n\n"
+      ;;     . processed current-line next-line unprocessed indentation-levels current-indentation
+      (cond
+       ;; the real end: this is reported to the outside world.
+       ((and (null? unprocessed) (not (null? indentation-levels)) (null? (cdr indentation-levels)))
+        ;; reverse the processed lines, because I use cons.
+        processed)
+       ;; the recursion end-condition
+       ((and (null? unprocessed))
+        ;; this is the last step. Nothing more to do except
+        ;; for rolling up the indentation levels.  return the
+        ;; new processed and unprocessed lists: this is a
+        ;; side-recursion
+        (values processed unprocessed))
+       ((null? indentation-levels)
+        (raise-exception (make-exception-from-throw 'wisp-programming-error  (list "The indentation-levels are null but the current-line is null: Something killed the indentation-levels."))))
+       (else ; now we come to the line-comparisons and indentation-counting.
+        (cond
+         ((line-empty-code? current-line)
+          ;; We cannot process indentation without
+          ;; code. Just switch to the next line. This should
+          ;; only happen at the start of the recursion.
+          (loop
+           processed
+           (cdr unprocessed)
+           indentation-levels))
+         ((and (line-empty-code? next-line) (<= 2 (length unprocessed)))
+          ;; take out the next-line from unprocessed.
+          (loop
+           processed
+           (cons current-line
+                 (cdr (cdr unprocessed)))
+           indentation-levels))
+         ((> current-indentation current-line-indentation)
+          ;; this just steps back one level via the side-recursion.
+          (let ((previous-indentation (car (cdr indentation-levels))))
+            (if (<= current-line-indentation previous-indentation)
+                (values processed unprocessed)
+                (begin ;; not yet used level! TODO: maybe throw an error here instead of a warning.
+                  (let ((linenumber (- (length lines) (length unprocessed))))
+                    (format (current-error-port) ";;; WARNING:~A: used lower but undefined indentation level (line ~A of the current chunk: ~S). This makes refactoring much more error-prone, therefore it might become an error in a later version of Wisp.\n" (source-property current-line 'line) linenumber (cdr current-line)))
+                  (loop
+                   processed
+                   unprocessed
+                   (cons ; recursion via the indentation-levels
+                    current-line-indentation
+                    (cdr indentation-levels)))))))
+         ((= current-indentation current-line-indentation)
+          (let
+              ((line (line-finalize current-line))
+               (next-line-indentation (line-real-indent next-line)))
+            (cond
+             ((>= current-line-indentation next-line-indentation)
+              ;; simple recursiive step to the next line
+              (loop
+               (append processed
+                       (if (line-continues? current-line)
+                           line
+                           (wisp-add-source-properties-from line (list line))))
+               (cdr unprocessed); recursion here
+               indentation-levels))
+             ((< current-line-indentation next-line-indentation)
+              ;; side-recursion via a sublist
+              (let-values
+                  (((sub-processed sub-unprocessed)
+                    (loop
+                     line
+                     (cdr unprocessed); recursion here
+                     indentation-levels)))
+                (loop
+                 (append processed (list sub-processed))
+                 sub-unprocessed ; simply use the recursion from the sub-recursion
+                 indentation-levels))))))
+         ((< current-indentation current-line-indentation)
+          (loop
+           processed
+           unprocessed
+           (cons ; recursion via the indentation-levels
+            current-line-indentation
+            indentation-levels)))
+         (else
+          (raise-exception (make-exception-from-throw 'wisp-not-implemented (list
+                 (format #f "Need to implement further line comparison: current: ~A, next: ~A, processed: ~A."
+                         current-line next-line processed)))))))))))
 
 
 (define (wisp-scheme-replace-inline-colons lines)
-         "Replace inline colons by opening parens which close at the end of the line"
-         (let loop
-           ((processed '())
-             (unprocessed lines))
-           (if (null? unprocessed)
-                processed
-                (loop
-                  (append processed (list (line-replace-inline-colons (car unprocessed))))
-                  (cdr unprocessed)))))
+  "Replace inline colons by opening parens which close at the end of the line"
+  (let loop
+      ((processed '())
+       (unprocessed lines))
+    (if (null? unprocessed)
+        processed
+        (loop
+         (append processed (list (line-replace-inline-colons (car unprocessed))))
+         (cdr unprocessed)))))
 
 
 (define (wisp-scheme-strip-indentation-markers lines)
-         "Strip the indentation markers from the beginning of the lines"
-         (let loop
-           ((processed '())
-             (unprocessed lines))
-           (if (null? unprocessed)
-                processed
-                (loop
-                  (append processed (cdr (car unprocessed)))
-                  (cdr unprocessed)))))
+  "Strip the indentation markers from the beginning of the lines"
+  (let loop
+      ((processed '())
+       (unprocessed lines))
+    (if (null? unprocessed)
+        processed
+        (loop
+         (append processed (cdr (car unprocessed)))
+         (cdr unprocessed)))))
 
 (define (wisp-unescape-underscore-and-colon code)
   "replace \\_ and \\: by _ and :"
   (cond ((list? code) (map wisp-unescape-underscore-and-colon code))
-      ((eq? code '\:) ':)
-      ;; Look for symbols like \____ and remove the \.
-      ((symbol? code)
-       (let ((as-string (symbol->string code)))
-         (if (and (>= (string-length as-string) 2) ; at least a single underscore
-                  (char=? (string-ref as-string 0) #\\)
-                  (string-every #\_ (substring as-string 1)))
-             (string->symbol (substring as-string 1))
-             code)))
-     (#t code)))
+        ((eq? code '\:) ':)
+        ;; Look for symbols like \____ and remove the \.
+        ((symbol? code)
+         (let ((as-string (symbol->string code)))
+           (if (and (>= (string-length as-string) 2) ; at least a single underscore
+                    (char=? (string-ref as-string 0) #\\)
+                    (string-every #\_ (substring as-string 1)))
+               (string->symbol (substring as-string 1))
+               code)))
+        (#t code)))
 
 
 (define (wisp-replace-empty-eof code)
-         "replace ((#<eof>)) by ()"
-         ; FIXME: Actually this is a hack which fixes a bug when the
-         ; parser hits files with only hashbang and comments.
-         (if (and (not (null? code)) (pair? (car code)) (eof-object? (car (car code))) (null? (cdr code)) (null? (cdr (car code))))
-              (list)
-              code))
+  "replace ((#<eof>)) by ()"
+  ;; This is a hack which fixes a bug when the
+  ;; parser hits files with only hashbang and comments.
+  (if (and (not (null? code)) (pair? (car code)) (eof-object? (car (car code))) (null? (cdr code)) (null? (cdr (car code))))
+      (list)
+      code))
 
 
 (define (wisp-replace-paren-quotation-repr code)
-         "Replace lists starting with a quotation symbol by
+  "Replace lists starting with a quotation symbol by
          quoted lists."
-         (match code
-             (('REPR-QUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-                (list 'quote (map wisp-replace-paren-quotation-repr a)))
-             ((a ... 'REPR-QUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b); this is the quoted empty list 
-                (append
-                        (map wisp-replace-paren-quotation-repr a)
-                        (list (list 'quote (map wisp-replace-paren-quotation-repr b)))))
-             (('REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd 'REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-                (list 'quasiquote (list 'unquote (map wisp-replace-paren-quotation-repr a))))
-             (('REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-                (list 'unquote (map wisp-replace-paren-quotation-repr a)))
-             ((a ... 'REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b)
-                (append
-                        (map wisp-replace-paren-quotation-repr a)
-                        (list (list 'unquote (map wisp-replace-paren-quotation-repr b)))))
-             (('REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-                (list 'quasiquote (map wisp-replace-paren-quotation-repr a)))
-             ((a ... 'REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b); this is the quoted empty list 
-                (append
-                        (map wisp-replace-paren-quotation-repr a)
-                        (list (list 'quasiquote (map wisp-replace-paren-quotation-repr b)))))
-             (('REPR-UNQUOTESPLICING-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-                (list 'unquote-splicing (map wisp-replace-paren-quotation-repr a)))
-             (('REPR-SYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-                (list 'syntax (map wisp-replace-paren-quotation-repr a)))
-             (('REPR-UNSYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-                (list 'unsyntax (map wisp-replace-paren-quotation-repr a)))
-             (('REPR-QUASISYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-                (list 'quasisyntax (map wisp-replace-paren-quotation-repr a)))
-             (('REPR-UNSYNTAXSPLICING-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-                (list 'unsyntax-splicing (map wisp-replace-paren-quotation-repr a)))
-             ;; literal array as start of a line: # (a b) c -> (#(a b) c)
-             ((#\# a ...)
-               (with-input-from-string ;; hack to defer to read
-                   (string-append "#"
-                       (with-output-to-string
-                           (λ ()
-                             (write (map wisp-replace-paren-quotation-repr a)
-                                     (current-output-port)))))
-                   read))
-             ((a ...)
-               (map wisp-replace-paren-quotation-repr a))
-             (a
-               a)))
+  (match code
+    (('REPR-QUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+     (list 'quote (map wisp-replace-paren-quotation-repr a)))
+    ((a ... 'REPR-QUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b); this is the quoted empty list
+     (append
+      (map wisp-replace-paren-quotation-repr a)
+      (list (list 'quote (map wisp-replace-paren-quotation-repr b)))))
+    (('REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd 'REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+     (list 'quasiquote (list 'unquote (map wisp-replace-paren-quotation-repr a))))
+    (('REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+     (list 'unquote (map wisp-replace-paren-quotation-repr a)))
+    ((a ... 'REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b)
+     (append
+      (map wisp-replace-paren-quotation-repr a)
+      (list (list 'unquote (map wisp-replace-paren-quotation-repr b)))))
+    (('REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+     (list 'quasiquote (map wisp-replace-paren-quotation-repr a)))
+    ((a ... 'REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b); this is the quoted empty list
+     (append
+      (map wisp-replace-paren-quotation-repr a)
+      (list (list 'quasiquote (map wisp-replace-paren-quotation-repr b)))))
+    (('REPR-UNQUOTESPLICING-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+     (list 'unquote-splicing (map wisp-replace-paren-quotation-repr a)))
+    (('REPR-SYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+     (list 'syntax (map wisp-replace-paren-quotation-repr a)))
+    (('REPR-UNSYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+     (list 'unsyntax (map wisp-replace-paren-quotation-repr a)))
+    (('REPR-QUASISYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+     (list 'quasisyntax (map wisp-replace-paren-quotation-repr a)))
+    (('REPR-UNSYNTAXSPLICING-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+     (list 'unsyntax-splicing (map wisp-replace-paren-quotation-repr a)))
+    ;; literal array as start of a line: # (a b) c -> (#(a b) c)
+    ((#\# a ...)
+     (with-input-from-string ;; hack to defer to read
+         (string-append "#"
+                        (with-output-to-string
+                          (λ ()
+                            (write (map wisp-replace-paren-quotation-repr a)
+                                   (current-output-port)))))
+       read))
+    ((a ...)
+     (map wisp-replace-paren-quotation-repr a))
+    (a
+     a)))
 
 (define (wisp-make-improper code)
-         "Turn (a #{.}# b) into the correct (a . b).
+  "Turn (a #{.}# b) into the correct (a . b).
 
 read called on a single dot creates a variable named #{.}# (|.|
 in r7rs). Due to parsing the indentation before the list
@@ -676,86 +660,85 @@ when it reads a dot. So we have to take another pass over the
 code to recreate the improper lists.
 
 Match is awesome!"
-         (let
-           ((improper
-               (match code
-                  ((a ... b 'REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd c)
-                    (append (map wisp-make-improper a) 
-                      (cons (wisp-make-improper b) (wisp-make-improper c))))
-                  ((a ...)
-                    (map wisp-make-improper a))
-                  (a
-                    a))))
-           (define (syntax-error li msg)
-                   (throw 'wisp-syntax-error (format #f "incorrect dot-syntax #{.}# in code: ~A: ~A" msg li)))
-           (if #t
-            improper
-            (let check
-             ((tocheck improper))
-             (match tocheck
-               ; lists with only one member
-               (('REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd)
-                 (syntax-error tocheck "list with the period as only member"))
-               ; list with remaining dot.
-               ((a ...)
-                 (if (and (member repr-dot a))
-                      (syntax-error tocheck "leftover period in list")
-                      (map check a)))
-               ; simple pair - this and the next do not work when parsed from wisp-scheme itself. Why?
-               (('REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd . c)
-                 (syntax-error tocheck "dot as first element in already improper pair"))
-               ; simple pair, other way round
-               ((a . 'REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd)
-                 (syntax-error tocheck "dot as last element in already improper pair"))
-               ; more complex pairs
-               ((? pair? a)
-                 (let 
-                   ((head (drop-right a 1))
-                     (tail (last-pair a)))
-                   (cond
-                    ((equal? repr-dot (car tail))
-                      (syntax-error tocheck "equal? repr-dot : car tail"))
-                    ((equal? repr-dot (cdr tail))
-                      (syntax-error tocheck "equal? repr-dot : cdr tail"))
-                    ((member repr-dot head)
-                      (syntax-error tocheck "member repr-dot head"))
-                    (else
-                      a))))
-               (a
-                 a))))))
+  (let
+      ((improper
+        (match code
+          ((a ... b 'REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd c)
+           (append (map wisp-make-improper a)
+                   (cons (wisp-make-improper b) (wisp-make-improper c))))
+          ((a ...)
+           (map wisp-make-improper a))
+          (a
+           a))))
+    (define (syntax-error li msg)
+      (raise-exception (make-exception-from-throw 'wisp-syntax-error (list (format #f "incorrect dot-syntax #{.}# in code: ~A: ~A" msg li)))))
+    (if #t
+        improper
+        (let check
+            ((tocheck improper))
+          (match tocheck
+            ;; lists with only one member
+            (('REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd)
+             (syntax-error tocheck "list with the period as only member"))
+            ;; list with remaining dot.
+            ((a ...)
+             (if (and (member repr-dot a))
+                 (syntax-error tocheck "leftover period in list")
+                 (map check a)))
+            ;; simple pair - this and the next do not work when parsed from wisp-scheme itself. Why?
+            (('REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd . c)
+             (syntax-error tocheck "dot as first element in already improper pair"))
+            ;; simple pair, other way round
+            ((a . 'REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd)
+             (syntax-error tocheck "dot as last element in already improper pair"))
+            ;; more complex pairs
+            ((? pair? a)
+             (let
+                 ((head (drop-right a 1))
+                  (tail (last-pair a)))
+               (cond
+                ((equal? repr-dot (car tail))
+                 (syntax-error tocheck "equal? repr-dot : car tail"))
+                ((equal? repr-dot (cdr tail))
+                 (syntax-error tocheck "equal? repr-dot : cdr tail"))
+                ((member repr-dot head)
+                 (syntax-error tocheck "member repr-dot head"))
+                (else
+                 a))))
+            (a
+             a))))))
 
 (define (wisp-scheme-read-chunk port)
-    "Read and parse one chunk of wisp-code"
-    (with-fluids ((%read-hash-procedures (fluid-ref %read-hash-procedures)))
-      (read-hash-extend #\# (lambda args #\#))
-      (let ((lines (wisp-scheme-read-chunk-lines port)))
-           (wisp-make-improper
-             (wisp-replace-empty-eof
-               (wisp-unescape-underscore-and-colon
-                 (wisp-replace-paren-quotation-repr
-                   (wisp-propagate-source-properties
-                     (wisp-scheme-indentation-to-parens lines)))))))))
+  "Read and parse one chunk of wisp-code"
+  (with-fluids ((%read-hash-procedures (fluid-ref %read-hash-procedures)))
+    (read-hash-extend #\# (lambda args #\#))
+    (let ((lines (wisp-scheme-read-chunk-lines port)))
+      (wisp-make-improper
+       (wisp-replace-empty-eof
+        (wisp-unescape-underscore-and-colon
+         (wisp-replace-paren-quotation-repr
+          (wisp-propagate-source-properties
+           (wisp-scheme-indentation-to-parens lines)))))))))
 
 (define (wisp-scheme-read-all port)
-         "Read all chunks from the given port"
-         (let loop
-           ((tokens '()))
-           (cond
-             ((eof-object? (peek-char port))
-               tokens)
-             (else
-               (loop
-                 (append tokens (wisp-scheme-read-chunk port)))))))
+  "Read all chunks from the given port"
+  (let loop
+      ((tokens '()))
+    (cond
+     ((eof-object? (peek-char port))
+      tokens)
+     (else
+      (loop
+       (append tokens (wisp-scheme-read-chunk port)))))))
 
 (define (wisp-scheme-read-file path)
-         (call-with-input-file path wisp-scheme-read-all))
+  (call-with-input-file path wisp-scheme-read-all))
 
 (define (wisp-scheme-read-file-chunk path)
-         (call-with-input-file path wisp-scheme-read-chunk))
+  (call-with-input-file path wisp-scheme-read-chunk))
 
 (define (wisp-scheme-read-string str)
-         (call-with-input-string str wisp-scheme-read-all))
+  (call-with-input-string str wisp-scheme-read-all))
 
 (define (wisp-scheme-read-string-chunk str)
-         (call-with-input-string str wisp-scheme-read-chunk))
-
+  (call-with-input-string str wisp-scheme-read-chunk))
-- 
2.41.0

From 8bacc9f43c3c5ffe1634a4e3fadda90ce4bdebcc Mon Sep 17 00:00:00 2001
From: Arne Babenhauserheide <arne_bab@web.de>
Date: Sat, 12 Aug 2023 23:13:26 +0200
Subject: [PATCH 07/11] SRFI-119 (wisp): change lang enter message

* module/language/wisp/spec.scm (define-language): no period at end,
  because the actual message in the REPL adds a !
---
 module/language/wisp/spec.scm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/module/language/wisp/spec.scm b/module/language/wisp/spec.scm
index fde08b429..e6dbf1764 100644
--- a/module/language/wisp/spec.scm
+++ b/module/language/wisp/spec.scm
@@ -51,7 +51,7 @@
                (car chunk))))))
 
 (define-language wisp
-  #:title "Wisp Scheme Syntax. See SRFI-119 for details."
+  #:title "Wisp Scheme Syntax. See SRFI-119 for details"
   ; . #:reader read-one-wisp-sexp
   #:reader read-one-wisp-sexp ; : lambda (port env) : let ((x (read-one-wisp-sexp port env))) (display x)(newline) x ;
   #:compilers `((tree-il . ,compile-tree-il))
-- 
2.41.0

From e79472e185027316b8195c8fbe502bd0c819fcaa Mon Sep 17 00:00:00 2001
From: Arne Babenhauserheide <arne_bab@web.de>
Date: Sat, 12 Aug 2023 23:17:57 +0200
Subject: [PATCH 08/11] SRFI-119 (wisp): simplify for review

* module/language/wisp/spec.scm (define-language): do not set
  simple-format as formatter for the reader
---
 module/language/wisp/spec.scm | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/module/language/wisp/spec.scm b/module/language/wisp/spec.scm
index e6dbf1764..1efd3e8b2 100644
--- a/module/language/wisp/spec.scm
+++ b/module/language/wisp/spec.scm
@@ -67,11 +67,6 @@
       ;; compile-time changes to `current-reader' are
       ;; limited to the current compilation unit.
       (module-define! m 'current-reader (make-fluid))
-      ;; Default to `simple-format', as is the case until
-      ;; (ice-9 format) is loaded. This allows
-      ;; compile-time warnings to be emitted when using
-      ;; unsupported options.
-      (module-set! m 'format simple-format)
       m)))
 
 
-- 
2.41.0

From 5cd837c71683dd5de51837f859450dcdbc99d83e Mon Sep 17 00:00:00 2001
From: Arne Babenhauserheide <arne_bab@web.de>
Date: Sun, 13 Aug 2023 11:35:23 +0200
Subject: [PATCH 09/11] SRFI-119 (wisp): Add source-property tests

* module/language/wisp.scm (wisp-add-source-properties-from/when-required):
  add the source properties from source to target if target has no
  source-properties.
* module/language/wisp.scm (wisp-propagate-source-properties):
  fix source property propagation

* module/language/wisp.scm (wisp-scheme-read-chunk-lines
    wisp-unescape-underscore-and-colon wisp-unescape-underscore-and-colon
    wisp-replace-paren-quotation-repr wisp-make-improper): preserve source
  properties

* test-suite/tests/srfi-119.test (top-level): add testgroup
  wisp-source-properties
---
 module/language/wisp.scm       | 181 +++++++++++++++++++--------------
 test-suite/tests/srfi-119.test |  10 +-
 2 files changed, 114 insertions(+), 77 deletions(-)

diff --git a/module/language/wisp.scm b/module/language/wisp.scm
index acc1f0725..812a8bad0 100644
--- a/module/language/wisp.scm
+++ b/module/language/wisp.scm
@@ -234,7 +234,10 @@
       (let ((next-char (peek-char port)))
         (cond
          ((eof-object? next-char)
-          (append indent-and-symbols (list (apply make-line currentindent currentsymbols))))
+          (let ((line (apply make-line currentindent currentsymbols)))
+            (set-source-property! line 'filename (port-filename port))
+            (set-source-property! line 'line (port-line port))
+            (append indent-and-symbols (list line))))
          ((and in-indent? (zero? currentindent) (not in-comment?) (not (null? indent-and-symbols)) (not in-underscoreindent?) (not (or (equal? #\space next-char) (equal? #\newline next-char) (equal? (string-ref ";" 0) next-char))))
           (append indent-and-symbols)); top-level form ends chunk
          ((chunk-ends-with-period currentsymbols next-char)
@@ -414,6 +417,12 @@
       #f))
   target)
 
+(define (wisp-add-source-properties-from/when-required source target)
+  "Copy the source properties if target has none."
+  (if (null? (source-properties target))
+      (wisp-add-source-properties-from source target)
+      target))
+
 (define (wisp-propagate-source-properties code)
   "Propagate the source properties from the sourrounding list into every part of the code."
   (let loop
@@ -430,12 +439,15 @@
       processed)
      (else
       (let ((line (car unprocessed)))
-        (if (null? (source-properties unprocessed))
-            (wisp-add-source-properties-from line unprocessed)
-            (wisp-add-source-properties-from unprocessed line))
-        (loop
-         (append processed (list (wisp-propagate-source-properties line)))
-         (cdr unprocessed)))))))
+        (wisp-add-source-properties-from/when-required line unprocessed)
+        (wisp-add-source-properties-from/when-required code unprocessed)
+        (wisp-add-source-properties-from/when-required unprocessed line)
+        (wisp-add-source-properties-from/when-required unprocessed code)
+        (let ((processed (append processed (list (wisp-propagate-source-properties line)))))
+          ;; must propagate from line, because unprocessed and code can be null, then they cannot keep source-properties.
+          (wisp-add-source-properties-from/when-required line processed)
+          (loop processed
+                (cdr unprocessed))))))))
 
 (define* (wisp-scheme-indentation-to-parens lines)
   "Add parentheses to lines and remove the indentation markers"
@@ -580,17 +592,19 @@
 
 (define (wisp-unescape-underscore-and-colon code)
   "replace \\_ and \\: by _ and :"
-  (cond ((list? code) (map wisp-unescape-underscore-and-colon code))
-        ((eq? code '\:) ':)
-        ;; Look for symbols like \____ and remove the \.
-        ((symbol? code)
-         (let ((as-string (symbol->string code)))
-           (if (and (>= (string-length as-string) 2) ; at least a single underscore
-                    (char=? (string-ref as-string 0) #\\)
-                    (string-every #\_ (substring as-string 1)))
-               (string->symbol (substring as-string 1))
-               code)))
-        (#t code)))
+  (wisp-add-source-properties-from/when-required
+   code
+   (cond ((list? code) (map wisp-unescape-underscore-and-colon code))
+         ((eq? code '\:) ':)
+         ;; Look for symbols like \____ and remove the \.
+         ((symbol? code)
+          (let ((as-string (symbol->string code)))
+            (if (and (>= (string-length as-string) 2) ; at least a single underscore
+                     (char=? (string-ref as-string 0) #\\)
+                     (string-every #\_ (substring as-string 1)))
+                (string->symbol (substring as-string 1))
+                code)))
+         (#t code))))
 
 
 (define (wisp-replace-empty-eof code)
@@ -598,57 +612,59 @@
   ;; This is a hack which fixes a bug when the
   ;; parser hits files with only hashbang and comments.
   (if (and (not (null? code)) (pair? (car code)) (eof-object? (car (car code))) (null? (cdr code)) (null? (cdr (car code))))
-      (list)
+      (wisp-add-source-properties-from code (list))
       code))
 
 
 (define (wisp-replace-paren-quotation-repr code)
   "Replace lists starting with a quotation symbol by
          quoted lists."
-  (match code
-    (('REPR-QUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-     (list 'quote (map wisp-replace-paren-quotation-repr a)))
-    ((a ... 'REPR-QUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b); this is the quoted empty list
-     (append
-      (map wisp-replace-paren-quotation-repr a)
-      (list (list 'quote (map wisp-replace-paren-quotation-repr b)))))
-    (('REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd 'REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-     (list 'quasiquote (list 'unquote (map wisp-replace-paren-quotation-repr a))))
-    (('REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-     (list 'unquote (map wisp-replace-paren-quotation-repr a)))
-    ((a ... 'REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b)
-     (append
-      (map wisp-replace-paren-quotation-repr a)
-      (list (list 'unquote (map wisp-replace-paren-quotation-repr b)))))
-    (('REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-     (list 'quasiquote (map wisp-replace-paren-quotation-repr a)))
-    ((a ... 'REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b); this is the quoted empty list
-     (append
-      (map wisp-replace-paren-quotation-repr a)
-      (list (list 'quasiquote (map wisp-replace-paren-quotation-repr b)))))
-    (('REPR-UNQUOTESPLICING-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-     (list 'unquote-splicing (map wisp-replace-paren-quotation-repr a)))
-    (('REPR-SYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-     (list 'syntax (map wisp-replace-paren-quotation-repr a)))
-    (('REPR-UNSYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-     (list 'unsyntax (map wisp-replace-paren-quotation-repr a)))
-    (('REPR-QUASISYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-     (list 'quasisyntax (map wisp-replace-paren-quotation-repr a)))
-    (('REPR-UNSYNTAXSPLICING-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
-     (list 'unsyntax-splicing (map wisp-replace-paren-quotation-repr a)))
-    ;; literal array as start of a line: # (a b) c -> (#(a b) c)
-    ((#\# a ...)
-     (with-input-from-string ;; hack to defer to read
-         (string-append "#"
-                        (with-output-to-string
-                          (λ ()
-                            (write (map wisp-replace-paren-quotation-repr a)
-                                   (current-output-port)))))
-       read))
-    ((a ...)
-     (map wisp-replace-paren-quotation-repr a))
-    (a
-     a)))
+  (wisp-add-source-properties-from/when-required
+   code
+   (match code
+     (('REPR-QUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+      (list 'quote (map wisp-replace-paren-quotation-repr a)))
+     ((a ... 'REPR-QUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b); this is the quoted empty list
+      (append
+       (map wisp-replace-paren-quotation-repr a)
+       (list (list 'quote (map wisp-replace-paren-quotation-repr b)))))
+     (('REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd 'REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+      (list 'quasiquote (list 'unquote (map wisp-replace-paren-quotation-repr a))))
+     (('REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+      (list 'unquote (map wisp-replace-paren-quotation-repr a)))
+     ((a ... 'REPR-UNQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b)
+      (append
+       (map wisp-replace-paren-quotation-repr a)
+       (list (list 'unquote (map wisp-replace-paren-quotation-repr b)))))
+     (('REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+      (list 'quasiquote (map wisp-replace-paren-quotation-repr a)))
+     ((a ... 'REPR-QUASIQUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd b); this is the quoted empty list
+      (append
+       (map wisp-replace-paren-quotation-repr a)
+       (list (list 'quasiquote (map wisp-replace-paren-quotation-repr b)))))
+     (('REPR-UNQUOTESPLICING-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+      (list 'unquote-splicing (map wisp-replace-paren-quotation-repr a)))
+     (('REPR-SYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+      (list 'syntax (map wisp-replace-paren-quotation-repr a)))
+     (('REPR-UNSYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+      (list 'unsyntax (map wisp-replace-paren-quotation-repr a)))
+     (('REPR-QUASISYNTAX-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+      (list 'quasisyntax (map wisp-replace-paren-quotation-repr a)))
+     (('REPR-UNSYNTAXSPLICING-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
+      (list 'unsyntax-splicing (map wisp-replace-paren-quotation-repr a)))
+     ;; literal array as start of a line: # (a b) c -> (#(a b) c)
+     ((#\# a ...)
+      (with-input-from-string ;; hack to defer to read
+          (string-append "#"
+                         (with-output-to-string
+                           (λ ()
+                             (write (map wisp-replace-paren-quotation-repr a)
+                                    (current-output-port)))))
+        read))
+     ((a ...)
+      (map wisp-replace-paren-quotation-repr a))
+     (a
+      a))))
 
 (define (wisp-make-improper code)
   "Turn (a #{.}# b) into the correct (a . b).
@@ -660,18 +676,6 @@ when it reads a dot. So we have to take another pass over the
 code to recreate the improper lists.
 
 Match is awesome!"
-  (let
-      ((improper
-        (match code
-          ((a ... b 'REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd c)
-           (append (map wisp-make-improper a)
-                   (cons (wisp-make-improper b) (wisp-make-improper c))))
-          ((a ...)
-           (map wisp-make-improper a))
-          (a
-           a))))
-    (define (syntax-error li msg)
-      (raise-exception (make-exception-from-throw 'wisp-syntax-error (list (format #f "incorrect dot-syntax #{.}# in code: ~A: ~A" msg li)))))
     (if #t
         improper
         (let check
@@ -706,7 +710,32 @@ Match is awesome!"
                 (else
                  a))))
             (a
-             a))))))
+  ;; local alias
+  (define (add-prop/req form)
+    (wisp-add-source-properties-from/when-required code form))
+  (wisp-add-source-properties-from/when-required
+   code
+   (let
+       ((improper
+         (match code
+           ((a ... b 'REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd c)
+            (set! is-proper? #f)
+            (wisp-add-source-properties-from/when-required
+             code
+             (append (map wisp-make-improper (map add-prop/req a))
+                     (cons (wisp-make-improper (add-prop/req b))
+                           (wisp-make-improper (add-prop/req c))))))
+           ((a ...)
+            (add-prop/req
+             (map wisp-make-improper (map add-prop/req a))))
+           (a
+            a))))
+     (define (syntax-error li msg)
+       (raise-exception
+        (make-exception-from-throw
+         'wisp-syntax-error
+         (list (format #f "incorrect dot-syntax #{.}# in code: ~A: ~A" msg li)))))
+              a)))))))
 
 (define (wisp-scheme-read-chunk port)
   "Read and parse one chunk of wisp-code"
diff --git a/test-suite/tests/srfi-119.test b/test-suite/tests/srfi-119.test
index a888df41d..f4a19a0a7 100644
--- a/test-suite/tests/srfi-119.test
+++ b/test-suite/tests/srfi-119.test
@@ -78,4 +78,12 @@ _  display \"hello\n\"
 (define (_)
    (display "hello\n"))
 
-(_)))))
+(_))))
+
+  ;; nesting with pairs
+  (pass-if (equal? (wisp->list "1 . 2\n3 4\n   5 . 6")
+                   '((1 . 2)(3 4 (5 . 6))))))
+
+(with-test-prefix "wisp-source-properties"
+  (pass-if (not (find null? (map source-properties (wisp->list "1 . 2\n3 4\n   5 . 6")))))
+  (pass-if (not (find null? (map source-properties (wisp->list "1 2\n3 4\n   5 6"))))))
-- 
2.41.0

From 7332c2c5bdc0a55a4c51fd8595b004ef768b675a Mon Sep 17 00:00:00 2001
From: Arne Babenhauserheide <arne_bab@web.de>
Date: Sun, 13 Aug 2023 11:39:19 +0200
Subject: [PATCH 10/11] SRFI-119 (wisp): improve indentation

* module/language/wisp.scm (indentation): restructure so auto-format
  creates less indentation.
---
 module/language/wisp.scm | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/module/language/wisp.scm b/module/language/wisp.scm
index 812a8bad0..506b37ea5 100644
--- a/module/language/wisp.scm
+++ b/module/language/wisp.scm
@@ -170,8 +170,8 @@
 (define (line-strip-continuation line)
   (if (line-continues? line)
       (apply make-line
-       (line-indent line)
-       (cdr (line-code line)))
+             (line-indent line)
+             (cdr (line-code line)))
       line))
 
 (define (line-strip-indentation-marker line)
@@ -462,9 +462,12 @@
               (cons
                (cons 0 (cdr (car lines)))
                (cdr lines)))
-        (raise-exception (make-exception-from-throw 'wisp-syntax-error (list
-               (format #f "The first symbol in a chunk must start at zero indentation. Indentation and line: ~A"
-                       (car lines)))))))
+        (raise-exception
+         (make-exception-from-throw
+          'wisp-syntax-error
+          (list
+           (format #f "The first symbol in a chunk must start at zero indentation. Indentation and line: ~A"
+                   (car lines)))))))
   (let loop
       ((processed '())
        (unprocessed lines)
@@ -496,7 +499,11 @@
         ;; side-recursion
         (values processed unprocessed))
        ((null? indentation-levels)
-        (raise-exception (make-exception-from-throw 'wisp-programming-error  (list "The indentation-levels are null but the current-line is null: Something killed the indentation-levels."))))
+        (raise-exception
+         (make-exception-from-throw
+          'wisp-programming-error
+          (list
+           "The indentation-levels are null but the current-line is null: Something killed the indentation-levels."))))
        (else ; now we come to the line-comparisons and indentation-counting.
         (cond
          ((line-empty-code? current-line)
@@ -562,9 +569,12 @@
             current-line-indentation
             indentation-levels)))
          (else
-          (raise-exception (make-exception-from-throw 'wisp-not-implemented (list
-                 (format #f "Need to implement further line comparison: current: ~A, next: ~A, processed: ~A."
-                         current-line next-line processed)))))))))))
+          (raise-exception
+           (make-exception-from-throw
+            'wisp-not-implemented
+            (list
+             (format #f "Need to implement further line comparison: current: ~A, next: ~A, processed: ~A."
+                     current-line next-line processed)))))))))))
 
 
 (define (wisp-scheme-replace-inline-colons lines)
-- 
2.41.0

From fa76d6d2937da46e445f8cf2eaaa82c14fc5ec4f Mon Sep 17 00:00:00 2001
From: Arne Babenhauserheide <arne_bab@web.de>
Date: Sun, 13 Aug 2023 11:40:20 +0200
Subject: [PATCH 11/11] SRFI-119 (wisp): stricter syntax checks

* module/language/wisp.scm (wisp-make-improper): run the syntax
  validation for illegal improper lists.
---
 module/language/wisp.scm | 69 ++++++++++++++++++++--------------------
 1 file changed, 35 insertions(+), 34 deletions(-)

diff --git a/module/language/wisp.scm b/module/language/wisp.scm
index 506b37ea5..b4e885eec 100644
--- a/module/language/wisp.scm
+++ b/module/language/wisp.scm
@@ -686,40 +686,7 @@ when it reads a dot. So we have to take another pass over the
 code to recreate the improper lists.
 
 Match is awesome!"
-    (if #t
-        improper
-        (let check
-            ((tocheck improper))
-          (match tocheck
-            ;; lists with only one member
-            (('REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd)
-             (syntax-error tocheck "list with the period as only member"))
-            ;; list with remaining dot.
-            ((a ...)
-             (if (and (member repr-dot a))
-                 (syntax-error tocheck "leftover period in list")
-                 (map check a)))
-            ;; simple pair - this and the next do not work when parsed from wisp-scheme itself. Why?
-            (('REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd . c)
-             (syntax-error tocheck "dot as first element in already improper pair"))
-            ;; simple pair, other way round
-            ((a . 'REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd)
-             (syntax-error tocheck "dot as last element in already improper pair"))
-            ;; more complex pairs
-            ((? pair? a)
-             (let
-                 ((head (drop-right a 1))
-                  (tail (last-pair a)))
-               (cond
-                ((equal? repr-dot (car tail))
-                 (syntax-error tocheck "equal? repr-dot : car tail"))
-                ((equal? repr-dot (cdr tail))
-                 (syntax-error tocheck "equal? repr-dot : cdr tail"))
-                ((member repr-dot head)
-                 (syntax-error tocheck "member repr-dot head"))
-                (else
-                 a))))
-            (a
+  (define is-proper? #t)
   ;; local alias
   (define (add-prop/req form)
     (wisp-add-source-properties-from/when-required code form))
@@ -745,6 +712,40 @@ Match is awesome!"
         (make-exception-from-throw
          'wisp-syntax-error
          (list (format #f "incorrect dot-syntax #{.}# in code: ~A: ~A" msg li)))))
+     (if is-proper?
+         improper
+         (let check
+             ((tocheck improper))
+           (match tocheck
+             ;; lists with only one member
+             (('REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd)
+              (syntax-error tocheck "list with the period as only member"))
+             ;; list with remaining dot.
+             ((a ...)
+              (if (and (member repr-dot a))
+                  (syntax-error tocheck "leftover period in list")
+                  (map check a)))
+             ;; simple pair - this and the next do not work when parsed from wisp-scheme itself. Why?
+             (('REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd . c)
+              (syntax-error tocheck "dot as first element in already improper pair"))
+             ;; simple pair, other way round
+             ((a . 'REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd)
+              (syntax-error tocheck "dot as last element in already improper pair"))
+             ;; more complex pairs
+             ((? pair? a)
+              (let
+                  ((head (drop-right a 1))
+                   (tail (last-pair a)))
+                (cond
+                 ((equal? repr-dot (car tail))
+                  (syntax-error tocheck "equal? repr-dot : car tail"))
+                 ((equal? repr-dot (cdr tail))
+                  (syntax-error tocheck "equal? repr-dot : cdr tail"))
+                 ((member repr-dot head)
+                  (syntax-error tocheck "member repr-dot head"))
+                 (else
+                  a))))
+             (a
               a)))))))
 
 (define (wisp-scheme-read-chunk port)
-- 
2.41.0



DIFF_WITHOUT_WHITESPACE

6 files changed, 214 insertions(+), 190 deletions(-)
am/bootstrap.am                |   3 +
doc/ref/srfi-modules.texi      |  11 +-
module/language/wisp.scm       | 329 ++++++++++++++++++++++-------------------
module/language/wisp/spec.scm  |  50 +++----
test-suite/Makefile.am         |   1 +
test-suite/tests/srfi-119.test |  10 +-

modified   am/bootstrap.am
@@ -393,6 +393,9 @@ SOURCES =					\
 						\
   system/syntax.scm				\
 						\
+  language/wisp.scm				\
+  language/wisp/spec.scm			\
+						\
   system/xref.scm				\
 						\
   sxml/apply-templates.scm			\
modified   doc/ref/srfi-modules.texi
@@ -64,7 +64,7 @@ get the relevant SRFI documents from the SRFI home page
 * SRFI-98::                     Accessing environment variables.
 * SRFI-105::                    Curly-infix expressions.
 * SRFI-111::                    Boxes.
-* SRFI-119::                    Wisp: simpler indentation-sensitive scheme.
+* SRFI-119::                    Wisp: simpler indentation-sensitive Scheme.
 * SRFI-171::                    Transducers
 @end menu
 
@@ -5664,13 +5664,14 @@ Set the contents of @var{box} to @var{value}.
 @end deffn
 
 @node SRFI-119
-@subsection SRFI-119 Wisp: simpler indentation-sensitive scheme.
+@subsection SRFI-119 Wisp: simpler indentation-sensitive Scheme.
 @cindex SRFI-119
 @cindex wisp
 
-The languages shipped in Guile include SRFI-119 (wisp), an encoding of
-Scheme that allows replacing parentheses with equivalent indentation and
-inline colons. See
+The languages shipped in Guile include SRFI-119, also referred to as
+@dfn{Wisp} (for ``Whitespace to Lisp''), an encoding of Scheme that
+allows replacing parentheses with equivalent indentation and inline
+colons.  See
 @uref{http://srfi.schemers.org/srfi-119/srfi-119.html, the specification
 of SRFI-119}.  Some examples:
 
modified   module/language/wisp.scm
@@ -33,19 +33,21 @@
 (define-module (language wisp)
   #:export (wisp-scheme-read-chunk wisp-scheme-read-all
                                    wisp-scheme-read-file-chunk wisp-scheme-read-file
-               wisp-scheme-read-string))
+                                   wisp-scheme-read-string)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-11); for let-values
+  #:use-module (srfi srfi-9); for records
+  #:use-module (ice-9 rw); for write-string/partial
+  #:use-module (ice-9 match))
 
-; use curly-infix by default
-(read-enable 'curly-infix)
-
-(use-modules
-  (srfi srfi-1)
-  (srfi srfi-11); for let-values
-  (ice-9 rw); for write-string/partial
-  (ice-9 match))
+;; use curly-infix by default
+(eval-when (expand load eval)
+  (read-enable 'curly-infix))
 
 
 ;; Helper functions for the indent-and-symbols data structure: '((indent token token ...) ...)
+(define make-line list)
+
 (define (line-indent line)
   (car line))
 
@@ -57,22 +59,23 @@
         indent)))
 
 (define (line-code line)
+  "Strip the indentation markers from the beginning of the line and preserve source-properties"
   (let ((code (cdr line)))
-             ; propagate source properties
+    ;; propagate source properties
     (when (not (null? code))
       (set-source-properties! code (source-properties line)))
     code))
 
-; literal values I need
+;; literal values I need
 (define readcolon
   (string->symbol ":"))
 
 (define wisp-uuid "e749c73d-c826-47e2-a798-c16c13cb89dd")
-; define an intermediate dot replacement with UUID to avoid clashes.
+;; define an intermediate dot replacement with UUID to avoid clashes.
 (define repr-dot ; .
   (string->symbol (string-append "REPR-DOT-" wisp-uuid)))
 
-; allow using reader additions as the first element on a line to prefix the list
+;; allow using reader additions as the first element on a line to prefix the list
 (define repr-quote ; '
   (string->symbol (string-append "REPR-QUOTE-" wisp-uuid)))
 (define repr-unquote ; ,
@@ -91,8 +94,8 @@
 (define repr-unsyntax-splicing ; #,@
   (string->symbol (string-append "REPR-UNSYNTAXSPLICING-" wisp-uuid)))
 
-; TODO: wrap the reader to return the repr of the syntax reader
-; additions
+;; TODO: wrap the reader to return the repr of the syntax reader
+;; additions
 
 (define (match-charlist-to-repr charlist)
   (let
@@ -160,20 +163,19 @@
 
 (define (line-empty? line)
   (and
-           ; if indent is -1, we stripped a comment, so the line was not really empty.
+   ;; if indent is -1, we stripped a comment, so the line was not really empty.
    (= 0 (line-indent line))
    (line-empty-code? line)))
 
 (define (line-strip-continuation line)
   (if (line-continues? line)
-              (append
-                (list
-                  (line-indent line))
+      (apply make-line
+             (line-indent line)
              (cdr (line-code line)))
       line))
 
 (define (line-strip-indentation-marker line)
-         "Strip the indentation markers from the beginning of the line"
+  "Strip the indentation markers from the beginning of the line for line-finalize without propagating source-properties (those are propagated in a second step)"
   (cdr line))
 
 (define (indent-level-reduction indentation-levels level select-fun)
@@ -189,7 +191,7 @@
        (cdr newlevels)
        (1+ diff)))
      (else
-               (throw 'wisp-syntax-error "Level ~A not found in the indentation-levels ~A.")))))
+      (raise-exception (make-exception-from-throw 'wisp-syntax-error (list (format #f "Level ~A not found in the indentation-levels ~A." level indentation-levels))))))))
 
 (define (indent-level-difference indentation-levels level)
   "Find how many indentation levels need to be popped off to find the given level."
@@ -210,74 +212,77 @@
        (equal? repr-dot
                (list-ref currentsymbols (- (length currentsymbols) 1)))))
 
+
 (define (wisp-scheme-read-chunk-lines port)
   (let loop
       ((indent-and-symbols (list)); '((5 "(foobar)" "\"yobble\"")(3 "#t"))
-             (inindent #t)
-             (inunderscoreindent (equal? #\_ (peek-char port)))
-             (incomment #f)
+       (in-indent? #t)
+       (in-underscoreindent? (equal? #\_ (peek-char port)))
+       (in-comment? #f)
        (currentindent 0)
        (currentsymbols '())
        (emptylines 0))
     (cond
-            ((>= emptylines 2); the chunk end has to be checked
-                              ; before we look for new chars in the
-                              ; port to make execution in the REPL
-                              ; after two empty lines work
-                              ; (otherwise it shows one more line).
+     ((>= emptylines 2)
+      ;; the chunk end has to be checked
+      ;; before we look for new chars in the
+      ;; port to make execution in the REPL
+      ;; after two empty lines work
+      ;; (otherwise it shows one more line).
       indent-and-symbols)
      (else
       (let ((next-char (peek-char port)))
         (cond
          ((eof-object? next-char)
-                   (append indent-and-symbols (list (append (list currentindent) currentsymbols))))
-                 ((and inindent (zero? currentindent) (not incomment) (not (null? indent-and-symbols)) (not inunderscoreindent) (not (or (equal? #\space next-char) (equal? #\newline next-char) (equal? (string-ref ";" 0) next-char))))
+          (let ((line (apply make-line currentindent currentsymbols)))
+            (set-source-property! line 'filename (port-filename port))
+            (set-source-property! line 'line (port-line port))
+            (append indent-and-symbols (list line))))
+         ((and in-indent? (zero? currentindent) (not in-comment?) (not (null? indent-and-symbols)) (not in-underscoreindent?) (not (or (equal? #\space next-char) (equal? #\newline next-char) (equal? (string-ref ";" 0) next-char))))
           (append indent-and-symbols)); top-level form ends chunk
          ((chunk-ends-with-period currentsymbols next-char)
-                   ; the line ends with a period. This is forbidden in
-                   ; SRFI-119. Use it to end the line in the REPL without
-                   ; showing continuation dots (...).
-                   (append indent-and-symbols (list (append (list currentindent) (drop-right currentsymbols 1)))))
-                 ((and inindent (equal? #\space next-char))
+          ;; the line ends with a period. This is forbidden in
+          ;; SRFI-119. Use it to end the line in the REPL without
+          ;; showing continuation dots (...).
+          (append indent-and-symbols (list (apply make-line currentindent (drop-right currentsymbols 1)))))
+         ((and in-indent? (equal? #\space next-char))
           (read-char port); remove char
           (loop
            indent-and-symbols
-                     #t ; inindent
-                     #f ; inunderscoreindent
-                     #f ; incomment
+           #t ; in-indent?
+           #f ; in-underscoreindent?
+           #f ; in-comment?
            (1+ currentindent)
            currentsymbols
            emptylines))
-                 ((and inunderscoreindent (equal? #\_ next-char))
+         ((and in-underscoreindent? (equal? #\_ next-char))
           (read-char port); remove char
           (loop
            indent-and-symbols
-                     #t ; inindent
-                     #t ; inunderscoreindent
-                     #f ; incomment
+           #t ; in-indent?
+           #t ; in-underscoreindent?
+           #f ; in-comment?
            (1+ currentindent)
            currentsymbols
            emptylines))
-                 ; any char but whitespace *after* underscoreindent is
-                 ; an error. This is stricter than the current wisp
-                 ; syntax definition. TODO: Fix the definition. Better
-                 ; start too strict. FIXME: breaks on lines with only
-                 ; underscores which should be empty lines.
-                 ((and inunderscoreindent (and (not (equal? #\space next-char)) (not (equal? #\newline next-char))))
-                   (throw 'wisp-syntax-error "initial underscores without following whitespace at beginning of the line after" (last indent-and-symbols)))
+         ;; any char but whitespace *after* underscoreindent is
+         ;; an error. This is stricter than the current wisp
+         ;; syntax definition. TODO: Fix the definition. Better
+         ;; start too strict. FIXME: breaks on lines with only
+         ;; underscores which should be empty lines.
+         ((and in-underscoreindent? (and (not (equal? #\space next-char)) (not (equal? #\newline next-char))))
+          (raise-exception (make-exception-from-throw 'wisp-syntax-error (list "initial underscores without following whitespace at beginning of the line after" (last indent-and-symbols)))))
          ((equal? #\newline next-char)
           (read-char port); remove the newline
-                   ; The following two lines would break the REPL by requiring one char too many.
-                   ; if : and (equal? #\newline next-char) : equal? #\return : peek-char port
-                   ;      read-char port ; remove a full \n\r. Damn special cases...
-                   (let* ; distinguish pure whitespace lines and lines
-                        ; with comment by giving the former zero
-                        ; indent. Lines with a comment at zero indent
-                        ; get indent -1 for the same reason - meaning
-                        ; not actually empty.
+          (let*
+              ;; distinguish pure whitespace lines and lines
+              ;; with comment by giving the former zero
+              ;; indent. Lines with a comment at zero indent
+              ;; get indent -1 for the same reason - meaning
+              ;; not actually empty.
               ((indent
                 (cond
-                           (incomment
+                 (in-comment?
                   (if (= 0 currentindent); specialcase
                       -1
                       currentindent))
@@ -285,35 +290,35 @@
                   currentindent)
                  (else
                   0)))
-                       (parsedline (append (list indent) currentsymbols))
+               (parsedline (apply make-line indent currentsymbols))
                (emptylines
                 (if (not (line-empty? parsedline))
                     0
                     (1+ emptylines))))
-                     (when (not (= 0 (length parsedline)))
-                         ; set the source properties to parsedline so we can try to add them later.
+            (when (not (= 0 (length (line-code parsedline))))
+              ;; set the source properties to parsedline so we can try to add them later.
               (set-source-property! parsedline 'filename (port-filename port))
               (set-source-property! parsedline 'line (port-line port)))
-                     ; TODO: If the line is empty. Either do it here and do not add it, just
-                     ; increment the empty line counter, or strip it later. Replace indent
-                     ; -1 by indent 0 afterwards.
+            ;; TODO: If the line is empty. Either do it here and do not add it, just
+            ;; increment the empty line counter, or strip it later. Replace indent
+            ;; -1 by indent 0 afterwards.
             (loop
              (append indent-and-symbols (list parsedline))
-                       #t ; inindent
+             #t ; in-indent?
              (if (<= 2 emptylines)
                  #f ; chunk ends here
                  (equal? #\_ (peek-char port))); are we in underscore indent?
-                       #f ; incomment
+             #f ; in-comment?
              0
              '()
              emptylines)))
-                 ((equal? #t incomment)
+         ((equal? #t in-comment?)
           (read-char port); remove one comment character
           (loop
            indent-and-symbols
-                     #f ; inindent 
-                     #f ; inunderscoreindent 
-                     #t ; incomment
+           #f ; in-indent?
+           #f ; in-underscoreindent?
+           #t ; in-comment?
            currentindent
            currentsymbols
            emptylines))
@@ -321,47 +326,47 @@
           (read-char port); remove char
           (loop
            indent-and-symbols
-                     #f ; inindent
-                     #f ; inunderscoreindent
-                     #f ; incomment
+           #f ; in-indent?
+           #f ; in-underscoreindent?
+           #f ; in-comment?
            currentindent
            currentsymbols
            emptylines))
-                          ; | cludge to appease the former wisp parser
-                          ; | used for bootstrapping which has a
-                          ; v problem with the literal comment char
+         ;; | cludge to appease the former wisp parser
+         ;; | used for bootstrapping which has a
+         ;; v problem with the literal comment char
          ((equal? (string-ref ";" 0) next-char)
           (loop
            indent-and-symbols
-                     #f ; inindent
-                     #f ; inunderscoreindent
-                     #t ; incomment
+           #f ; in-indent?
+           #f ; in-underscoreindent?
+           #t ; in-comment?
            currentindent
            currentsymbols
            emptylines))
          (else ; use the reader
           (loop
            indent-and-symbols
-                     #f ; inindent
-                     #f ; inunderscoreindent
-                     #f ; incomment
+           #f ; in-indent?
+           #f ; in-underscoreindent?
+           #f ; in-comment?
            currentindent
-                     ; this also takes care of the hashbang and leading comments.
+           ;; this also takes care of the hashbang and leading comments.
            (append currentsymbols (list (wisp-read port)))
            emptylines))))))))
 
 
 (define (line-code-replace-inline-colons line)
   "Replace inline colons by opening parens which close at the end of the line"
-         ; format #t "replace inline colons for line ~A\n" line
+  ;; format #t "replace inline colons for line ~A\n" line
   (let loop
       ((processed '())
        (unprocessed line))
     (cond
      ((null? unprocessed)
-               ; format #t "inline-colons processed line: ~A\n" processed
+      ;; format #t "inline-colons processed line: ~A\n" processed
       processed)
-             ; replace : . with nothing
+     ;; replace : . with nothing
      ((and (<= 2 (length unprocessed)) (equal? readcolon (car unprocessed)) (equal? repr-dot (car (cdr unprocessed))))
       (loop
        (append processed
@@ -369,7 +374,6 @@
        '()))
      ((equal? readcolon (car unprocessed))
       (loop
-                 ; FIXME: This should turn unprocessed into a list. 
        (append processed
                (list (loop '() (cdr unprocessed))))
        '()))
@@ -386,11 +390,8 @@
 
 (define (line-strip-lone-colon line)
   "A line consisting only of a colon is just a marked indentation level. We need to kill the colon before replacing inline colons."
-         (if
-           (equal?
-             (line-code line)
-             (list readcolon))
-           (list (line-indent line))
+  (if (equal? (line-code line) (list readcolon))
+      (make-line (line-indent line))
       line))
 
 (define (line-finalize line)
@@ -416,6 +417,12 @@
       #f))
   target)
 
+(define (wisp-add-source-properties-from/when-required source target)
+  "Copy the source properties if target has none."
+  (if (null? (source-properties target))
+      (wisp-add-source-properties-from source target)
+      target))
+
 (define (wisp-propagate-source-properties code)
   "Propagate the source properties from the sourrounding list into every part of the code."
   (let loop
@@ -432,12 +439,15 @@
       processed)
      (else
       (let ((line (car unprocessed)))
-               (if (null? (source-properties unprocessed))
-                   (wisp-add-source-properties-from line unprocessed)
-                   (wisp-add-source-properties-from unprocessed line))
-               (loop
-                 (append processed (list (wisp-propagate-source-properties line)))
-                 (cdr unprocessed)))))))
+        (wisp-add-source-properties-from/when-required line unprocessed)
+        (wisp-add-source-properties-from/when-required code unprocessed)
+        (wisp-add-source-properties-from/when-required unprocessed line)
+        (wisp-add-source-properties-from/when-required unprocessed code)
+        (let ((processed (append processed (list (wisp-propagate-source-properties line)))))
+          ;; must propagate from line, because unprocessed and code can be null, then they cannot keep source-properties.
+          (wisp-add-source-properties-from/when-required line processed)
+          (loop processed
+                (cdr unprocessed))))))))
 
 (define* (wisp-scheme-indentation-to-parens lines)
   "Add parentheses to lines and remove the indentation markers"
@@ -452,9 +462,12 @@
               (cons
                (cons 0 (cdr (car lines)))
                (cdr lines)))
-             (throw 'wisp-syntax-error
+        (raise-exception
+         (make-exception-from-throw
+          'wisp-syntax-error
+          (list
            (format #f "The first symbol in a chunk must start at zero indentation. Indentation and line: ~A"
-                 (car lines)))))
+                   (car lines)))))))
   (let loop
       ((processed '())
        (unprocessed lines)
@@ -463,57 +476,53 @@
         ((current-line
           (if (<= 1 (length unprocessed))
               (car unprocessed)
-                      (list 0))); empty code
+              (make-line 0))); empty code
          (next-line
           (if (<= 2 (length unprocessed))
               (car (cdr unprocessed))
-                      (list 0))); empty code
+              (make-line 0))); empty code
          (current-indentation
           (car indentation-levels))
          (current-line-indentation (line-real-indent current-line)))
-             ; format #t "processed: ~A\ncurrent-line: ~A\nnext-line: ~A\nunprocessed: ~A\nindentation-levels: ~A\ncurrent-indentation: ~A\n\n"
-             ;     . processed current-line next-line unprocessed indentation-levels current-indentation
+      ;; format #t "processed: ~A\ncurrent-line: ~A\nnext-line: ~A\nunprocessed: ~A\nindentation-levels: ~A\ncurrent-indentation: ~A\n\n"
+      ;;     . processed current-line next-line unprocessed indentation-levels current-indentation
       (cond
-                 ; the real end: this is reported to the outside world.
+       ;; the real end: this is reported to the outside world.
        ((and (null? unprocessed) (not (null? indentation-levels)) (null? (cdr indentation-levels)))
-                 ; display "done\n"
-                 ; reverse the processed lines, because I use cons.
+        ;; reverse the processed lines, because I use cons.
         processed)
-               ; the recursion end-condition
+       ;; the recursion end-condition
        ((and (null? unprocessed))
-                 ; display "last step\n"
-                 ; this is the last step. Nothing more to do except
-                 ; for rolling up the indentation levels.  return the
-                 ; new processed and unprocessed lists: this is a
-                 ; side-recursion
+        ;; this is the last step. Nothing more to do except
+        ;; for rolling up the indentation levels.  return the
+        ;; new processed and unprocessed lists: this is a
+        ;; side-recursion
         (values processed unprocessed))
        ((null? indentation-levels)
-                 ; display "indentation-levels null\n"
-                 (throw 'wisp-programming-error "The indentation-levels are null but the current-line is null: Something killed the indentation-levels."))
+        (raise-exception
+         (make-exception-from-throw
+          'wisp-programming-error
+          (list
+           "The indentation-levels are null but the current-line is null: Something killed the indentation-levels."))))
        (else ; now we come to the line-comparisons and indentation-counting.
         (cond
          ((line-empty-code? current-line)
-                       ; display "current-line empty\n"
-                       ; We cannot process indentation without
-                       ; code. Just switch to the next line. This should
-                       ; only happen at the start of the recursion.
-                       ; TODO: Somehow preserve the line-numbers.
+          ;; We cannot process indentation without
+          ;; code. Just switch to the next line. This should
+          ;; only happen at the start of the recursion.
           (loop
            processed
            (cdr unprocessed)
            indentation-levels))
          ((and (line-empty-code? next-line) (<= 2 (length unprocessed)))
-                       ; display "next-line empty\n"
-                       ; TODO: Somehow preserve the line-numbers.
-                       ; take out the next-line from unprocessed.
+          ;; take out the next-line from unprocessed.
           (loop
            processed
            (cons current-line
                  (cdr (cdr unprocessed)))
            indentation-levels))
          ((> current-indentation current-line-indentation)
-                       ; display "current-indent > next-line\n"
-                       ; this just steps back one level via the side-recursion.
+          ;; this just steps back one level via the side-recursion.
           (let ((previous-indentation (car (cdr indentation-levels))))
             (if (<= current-line-indentation previous-indentation)
                 (values processed unprocessed)
@@ -527,14 +536,12 @@
                     current-line-indentation
                     (cdr indentation-levels)))))))
          ((= current-indentation current-line-indentation)
-                       ; display "current-indent = next-line\n"
           (let
               ((line (line-finalize current-line))
                (next-line-indentation (line-real-indent next-line)))
             (cond
              ((>= current-line-indentation next-line-indentation)
-                             ; simple recursiive step to the next line
-                             ; display "current-line-indent >= next-line-indent\n"
+              ;; simple recursiive step to the next line
               (loop
                (append processed
                        (if (line-continues? current-line)
@@ -543,22 +550,18 @@
                (cdr unprocessed); recursion here
                indentation-levels))
              ((< current-line-indentation next-line-indentation)
-                             ; display "current-line-indent < next-line-indent\n"
-                             ; format #t "line: ~A\n" line
-                             ; side-recursion via a sublist
+              ;; side-recursion via a sublist
               (let-values
                   (((sub-processed sub-unprocessed)
                     (loop
                      line
                      (cdr unprocessed); recursion here
                      indentation-levels)))
-                               ; format #t "side-recursion:\n  sub-processed: ~A\n  processed: ~A\n\n" sub-processed processed
                 (loop
                  (append processed (list sub-processed))
                  sub-unprocessed ; simply use the recursion from the sub-recursion
                  indentation-levels))))))
          ((< current-indentation current-line-indentation)
-                       ; display "current-indent < next-line\n"
           (loop
            processed
            unprocessed
@@ -566,9 +569,12 @@
             current-line-indentation
             indentation-levels)))
          (else
-                       (throw 'wisp-not-implemented
+          (raise-exception
+           (make-exception-from-throw
+            'wisp-not-implemented
+            (list
              (format #f "Need to implement further line comparison: current: ~A, next: ~A, processed: ~A."
-                               current-line next-line processed)))))))))
+                     current-line next-line processed)))))))))))
 
 
 (define (wisp-scheme-replace-inline-colons lines)
@@ -596,6 +602,8 @@
 
 (define (wisp-unescape-underscore-and-colon code)
   "replace \\_ and \\: by _ and :"
+  (wisp-add-source-properties-from/when-required
+   code
    (cond ((list? code) (map wisp-unescape-underscore-and-colon code))
          ((eq? code '\:) ':)
          ;; Look for symbols like \____ and remove the \.
@@ -606,21 +614,23 @@
                      (string-every #\_ (substring as-string 1)))
                 (string->symbol (substring as-string 1))
                 code)))
-     (#t code)))
+         (#t code))))
 
 
 (define (wisp-replace-empty-eof code)
   "replace ((#<eof>)) by ()"
-         ; FIXME: Actually this is a hack which fixes a bug when the
-         ; parser hits files with only hashbang and comments.
+  ;; This is a hack which fixes a bug when the
+  ;; parser hits files with only hashbang and comments.
   (if (and (not (null? code)) (pair? (car code)) (eof-object? (car (car code))) (null? (cdr code)) (null? (cdr (car code))))
-              (list)
+      (wisp-add-source-properties-from code (list))
       code))
 
 
 (define (wisp-replace-paren-quotation-repr code)
   "Replace lists starting with a quotation symbol by
          quoted lists."
+  (wisp-add-source-properties-from/when-required
+   code
    (match code
      (('REPR-QUOTE-e749c73d-c826-47e2-a798-c16c13cb89dd a ...)
       (list 'quote (map wisp-replace-paren-quotation-repr a)))
@@ -664,7 +674,7 @@
      ((a ...)
       (map wisp-replace-paren-quotation-repr a))
      (a
-               a)))
+      a))))
 
 (define (wisp-make-improper code)
   "Turn (a #{.}# b) into the correct (a . b).
@@ -676,38 +686,52 @@ when it reads a dot. So we have to take another pass over the
 code to recreate the improper lists.
 
 Match is awesome!"
+  (define is-proper? #t)
+  ;; local alias
+  (define (add-prop/req form)
+    (wisp-add-source-properties-from/when-required code form))
+  (wisp-add-source-properties-from/when-required
+   code
    (let
        ((improper
          (match code
            ((a ... b 'REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd c)
-                    (append (map wisp-make-improper a) 
-                      (cons (wisp-make-improper b) (wisp-make-improper c))))
+            (set! is-proper? #f)
+            (wisp-add-source-properties-from/when-required
+             code
+             (append (map wisp-make-improper (map add-prop/req a))
+                     (cons (wisp-make-improper (add-prop/req b))
+                           (wisp-make-improper (add-prop/req c))))))
            ((a ...)
-                    (map wisp-make-improper a))
+            (add-prop/req
+             (map wisp-make-improper (map add-prop/req a))))
            (a
             a))))
      (define (syntax-error li msg)
-                   (throw 'wisp-syntax-error (format #f "incorrect dot-syntax #{.}# in code: ~A: ~A" msg li)))
-           (if #t
+       (raise-exception
+        (make-exception-from-throw
+         'wisp-syntax-error
+         (list (format #f "incorrect dot-syntax #{.}# in code: ~A: ~A" msg li)))))
+     (if is-proper?
          improper
          (let check
              ((tocheck improper))
            (match tocheck
-               ; lists with only one member
+             ;; lists with only one member
              (('REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd)
               (syntax-error tocheck "list with the period as only member"))
-               ; list with remaining dot.
+             ;; list with remaining dot.
              ((a ...)
               (if (and (member repr-dot a))
                   (syntax-error tocheck "leftover period in list")
                   (map check a)))
-               ; simple pair - this and the next do not work when parsed from wisp-scheme itself. Why?
+             ;; simple pair - this and the next do not work when parsed from wisp-scheme itself. Why?
              (('REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd . c)
               (syntax-error tocheck "dot as first element in already improper pair"))
-               ; simple pair, other way round
+             ;; simple pair, other way round
              ((a . 'REPR-DOT-e749c73d-c826-47e2-a798-c16c13cb89dd)
               (syntax-error tocheck "dot as last element in already improper pair"))
-               ; more complex pairs
+             ;; more complex pairs
              ((? pair? a)
               (let
                   ((head (drop-right a 1))
@@ -722,7 +746,7 @@ Match is awesome!"
                  (else
                   a))))
              (a
-                 a))))))
+              a)))))))
 
 (define (wisp-scheme-read-chunk port)
   "Read and parse one chunk of wisp-code"
@@ -758,4 +782,3 @@ Match is awesome!"
 
 (define (wisp-scheme-read-string-chunk str)
   (call-with-input-string str wisp-scheme-read-chunk))
-
modified   module/language/wisp/spec.scm
@@ -1,32 +1,25 @@
-;; Language interface for Wisp in Guile
+;;; Language interface for Wisp in Guile
 
-;;; adapted from guile-sweet: https://gitorious.org/nacre/guile-sweet/source/ae306867e371cb4b56e00bb60a50d9a0b8353109:sweet/common.scm
+;; Copyright (C) 2005--2014 by David A. Wheeler and Alan Manuel K. Gloria
+;; Copyright (C) 2014--2023 Arne Babenhauserheide.
+;; Copyright (C) 2023 Maxime Devos <maximedevos@telenet.be>
 
-;;; Copyright (C) 2005--2014 by David A. Wheeler and Alan Manuel K. Gloria
-;;; Copyright (C) 2014--2023 Arne Babenhauserheide.
-;;; Copyright (C) 2023 Maxime Devos <maximedevos@telenet.be>
+;;;; This library is free software; you can redistribute it and/or
+;;;; modify it under the terms of the GNU Lesser General Public
+;;;; License as published by the Free Software Foundation; either
+;;;; version 3 of the License, or (at your option) any later version.
+;;;;
+;;;; This library is distributed in the hope that it will be useful,
+;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;;; Lesser General Public License for more details.
+;;;;
+;;;; You should have received a copy of the GNU Lesser General Public
+;;;; License along with this library; if not, write to the Free Software
+;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
-;;; Permission is hereby granted, free of charge, to any person
-;;; obtaining a copy of this software and associated documentation
-;;; files (the "Software"), to deal in the Software without
-;;; restriction, including without limitation the rights to use, copy,
-;;; modify, merge, publish, distribute, sublicense, and/or sell copies
-;;; of the Software, and to permit persons to whom the Software is
-;;; furnished to do so, subject to the following conditions:
-;;;
-;;; The above copyright notice and this permission notice shall be
-;;; included in all copies or substantial portions of the Software.
-;;;
-;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-;;; BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-;;; ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-;;; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-;;; SOFTWARE.
+;; adapted from spec.scm: https://gitorious.org/nacre/guile-sweet/?p=nacre:guile-sweet.git;a=blob;f=sweet/spec.scm;hb=ae306867e371cb4b56e00bb60a50d9a0b8353109
 
-; adapted from spec.scm: https://gitorious.org/nacre/guile-sweet/source/ae306867e371cb4b56e00bb60a50d9a0b8353109:sweet/spec.scm
 (define-module (language wisp spec)
   #:use-module (language wisp)
   #:use-module (system base compile)
@@ -58,7 +51,7 @@
                (car chunk))))))
 
 (define-language wisp
-  #:title "Wisp Scheme Syntax. See SRFI-119 for details."
+  #:title "Wisp Scheme Syntax. See SRFI-119 for details"
   ; . #:reader read-one-wisp-sexp
   #:reader read-one-wisp-sexp ; : lambda (port env) : let ((x (read-one-wisp-sexp port env))) (display x)(newline) x ;
   #:compilers `((tree-il . ,compile-tree-il))
@@ -74,11 +67,6 @@
       ;; compile-time changes to `current-reader' are
       ;; limited to the current compilation unit.
       (module-define! m 'current-reader (make-fluid))
-      ;; Default to `simple-format', as is the case until
-      ;; (ice-9 format) is loaded. This allows
-      ;; compile-time warnings to be emitted when using
-      ;; unsupported options.
-      (module-set! m 'format simple-format)
       m)))
 
 
modified   test-suite/Makefile.am
@@ -162,6 +162,7 @@ SCM_TESTS = tests/00-initial-env.test		\
 	    tests/srfi-98.test			\
 	    tests/srfi-105.test			\
 	    tests/srfi-111.test			\
+	    tests/srfi-119.test			\
 	    tests/srfi-171.test			\
 	    tests/srfi-4.test			\
 	    tests/srfi-9.test			\
modified   test-suite/tests/srfi-119.test
@@ -78,4 +78,12 @@ _  display \"hello\n\"
 (define (_)
    (display "hello\n"))
 
-(_)))))
+(_))))
+
+  ;; nesting with pairs
+  (pass-if (equal? (wisp->list "1 . 2\n3 4\n   5 . 6")
+                   '((1 . 2)(3 4 (5 . 6))))))
+
+(with-test-prefix "wisp-source-properties"
+  (pass-if (not (find null? (map source-properties (wisp->list "1 . 2\n3 4\n   5 . 6")))))
+  (pass-if (not (find null? (map source-properties (wisp->list "1 2\n3 4\n   5 6"))))))




-- 
Unpolitisch sein
heißt politisch sein,
ohne es zu merken.
draketo.de

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 1125 bytes --]

  reply	other threads:[~2023-08-14 20:30 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-03 21:26 [PATCH] add language/wisp to Guile? Dr. Arne Babenhauserheide
2023-02-04 15:08 ` Maxime Devos
2023-02-04 15:46   ` Dr. Arne Babenhauserheide
2023-02-04 19:09     ` Maxime Devos
2023-02-04 21:35       ` Dr. Arne Babenhauserheide
2023-02-05 15:08         ` Maxime Devos
2023-02-14  8:32           ` Dr. Arne Babenhauserheide
2023-02-14 21:24             ` Dr. Arne Babenhauserheide
2023-02-14 23:01               ` Maxime Devos
2023-02-15  1:46                 ` Matt Wette
2023-02-16 21:38                   ` Dr. Arne Babenhauserheide
2023-02-17  1:26                     ` Matt Wette
2023-02-23 11:36                       ` Ludovic Courtès
2023-02-23 17:48                         ` Dr. Arne Babenhauserheide
2023-02-23 18:42                         ` Maxime Devos
2023-02-24 15:45                           ` Ludovic Courtès
2023-02-24 16:34                             ` Dr. Arne Babenhauserheide
2023-03-08 10:34                               ` Dr. Arne Babenhauserheide
2023-05-01  9:54                                 ` [PATCH] add SRFI-119 / language/wisp to Guile? (new patch, squashed) Dr. Arne Babenhauserheide
2023-06-10 16:40                                   ` Ludovic Courtès
2023-06-12 10:22                                     ` Maxime Devos
2023-08-10  6:28                                       ` Dr. Arne Babenhauserheide
2023-08-14 20:11                                         ` Dr. Arne Babenhauserheide
2023-08-14 20:30                                           ` Dr. Arne Babenhauserheide [this message]
2023-08-14 22:43                                           ` Dr. Arne Babenhauserheide
2023-08-18 10:29                                           ` Ludovic Courtès
2023-08-18 12:16                                             ` Dr. Arne Babenhauserheide
2023-08-18 17:50                                               ` Dr. Arne Babenhauserheide
2023-09-08 17:46                                               ` Dr. Arne Babenhauserheide
2023-10-05 14:10                                                 ` Dr. Arne Babenhauserheide
2023-10-10 23:04                                                   ` Dr. Arne Babenhauserheide
2023-10-27 22:05                                                     ` Dr. Arne Babenhauserheide
2024-01-09  7:05                                                       ` Dr. Arne Babenhauserheide
2024-01-19  8:21                                                         ` Dr. Arne Babenhauserheide
2024-03-11  1:16                                                           ` [PATCH] add SRFI-119 / language/wisp to Guile? (new patch with more tests, squashed) Dr. Arne Babenhauserheide
2024-01-19 12:10                                                         ` [PATCH] add SRFI-119 / language/wisp to Guile? (new patch, squashed) Christina O'Donnell
2024-01-19 21:37                                                           ` Ricardo Wurmus
2024-01-19 21:47                                                             ` Christina O'Donnell
2024-01-20 11:01                                                               ` Damien Mattei
2024-01-20 19:18                                                                 ` Dr. Arne Babenhauserheide
2024-01-20 22:59                                                                   ` Damien Mattei
2024-01-20 23:22                                                                     ` Dr. Arne Babenhauserheide
2024-01-21 23:21                                                                       ` Damien Mattei
2024-01-19 23:56                                                           ` Dr. Arne Babenhauserheide
2023-02-24 23:48                             ` [PATCH] add language/wisp to Guile? Maxime Devos
2023-02-24 23:51                               ` Maxime Devos
2023-02-25  0:15                                 ` Matt Wette
2023-02-25 10:42                                   ` Maxime Devos
2023-02-17 23:06                     ` Maxime Devos
2023-02-18  3:50                       ` Philip McGrath
2023-02-18 15:58                         ` Maxime Devos
2023-02-18 19:56                           ` Matt Wette
2023-02-21 12:09                             ` Dr. Arne Babenhauserheide
2023-02-26  7:45                           ` Philip McGrath
2023-02-26 15:42                             ` Maxime Devos
2023-02-26 16:14                               ` Dr. Arne Babenhauserheide
2023-02-26 17:58                               ` Matt Wette
2023-02-26 18:03                                 ` Dr. Arne Babenhauserheide
2023-02-26 18:20                                   ` Matt Wette
2023-02-26 21:39                                     ` Dr. Arne Babenhauserheide
2023-10-02 14:59                             ` Christine Lemmer-Webber
2023-10-02 21:46                               ` guile support for multiple languages [was: [PATCH] add language/wisp to Guile?] Matt Wette
2023-02-23  7:59                         ` [PATCH] add language/wisp to Guile? Maxime Devos
2023-02-23  8:51                           ` Dr. Arne Babenhauserheide
2023-02-23 18:04                             ` Maxime Devos
2023-02-23 18:22                               ` Maxime Devos
2023-02-23 18:36                               ` Maxime Devos
2023-02-23 18:37                               ` Maxime Devos
2023-02-15  8:36                 ` Dr. Arne Babenhauserheide
2023-02-15 20:13                   ` Maxime Devos
2023-02-16  7:01                     ` Dr. Arne Babenhauserheide
2023-02-16  8:03   ` Dr. Arne Babenhauserheide
2023-02-16 11:30     ` Maxime Devos
2023-02-16 21:35       ` Dr. Arne Babenhauserheide
2023-09-30 13:17 ` Christine Lemmer-Webber
2023-09-30 20:09   ` Maxime Devos
2023-10-02 14:48     ` Christine Lemmer-Webber

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=871qg58ikx.fsf@web.de \
    --to=arne_bab@web.de \
    --cc=guile-devel@gnu.org \
    --cc=ludo@gnu.org \
    --cc=maximedevos@telenet.be \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).