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 --]
next prev parent 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).