(Arne Babenhauserheide)
2014-10-16: v0.6.5 now uses the clean scheme read using wisp in the REPL. stable v0.6.5 v0.6.5 now uses the clean scheme read using wisp in the REPL.
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+wisp 0.6.5 (2014-10-16):
+- use wisp-scheme in the REPL.
+- safe dot representation for reading a literal dot (.) for creating improper lists.
+
wisp 0.6.4 (2014-09-02):
- an actually working wisp implementation for scheme (only) which uses the guile reader. This should be actually correct for scheme. And match-magic ☺
- polishing.
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
dnl run `autoreconf -i` to generate a configure script.
dnl Then run ./configure to generate a Makefile.
dnl Finally run make to generate the project.
-AC_INIT([wisp], [0.6.4],
+AC_INIT([wisp], [0.6.5],
[arne_bab@web.de])
# Check for programs I need for my build
AC_CANONICAL_TARGET
diff --git a/tests/strangecomments.scm b/tests/strangecomments.scm
--- a/tests/strangecomments.scm
+++ b/tests/strangecomments.scm
@@ -8,8 +8,6 @@
; broken
; expected:
-; ((2 (foo)) (2) (0) (0) (2 foo : moo
-; ) (4 #{.}# [goo #{.}# hoo]))
(display
(call-with-input-string " (foo) ; bar\n ; nop \n\n; nup\n; nup \n \n\n\n foo : moo \"\n\" \n___ . [goo . hoo]" wisp-scheme-read-chunk))
(newline)
diff --git a/tests/strangecomments.w b/tests/strangecomments.w
--- a/tests/strangecomments.w
+++ b/tests/strangecomments.w
@@ -8,8 +8,6 @@ newline
; broken
; expected:
-; ((2 (foo)) (2) (0) (0) (2 foo : moo
-; ) (4 #{.}# [goo #{.}# hoo]))
display
call-with-input-string " (foo) ; bar\n ; nop \n\n; nup\n; nup \n \n\n\n foo : moo \"\n\" \n___ . [goo . hoo]" wisp-scheme-read-chunk
newline
diff --git a/wisp-reader.w b/wisp-reader.w
--- a/wisp-reader.w
+++ b/wisp-reader.w
@@ -11,6 +11,7 @@
; adapted from spec.scm: https://gitorious.org/nacre/guile-sweet/source/ae306867e371cb4b56e00bb60a50d9a0b8353109:sweet/spec.scm
define-module : language wisp spec
. #:use-module : wisp
+ . #:use-module : wisp-scheme
. #:use-module : system base compile
. #:use-module : system base language
. #:export : wisp
@@ -49,10 +50,16 @@ define : read-one-wisp-sexp port env
read-wisp-chunk
try-pending
+define : wisp-scheme-read-chunk-env port env
+ cons 'begin : wisp-scheme-read-chunk port
+
define-language wisp
. #:title "Wisp Scheme Syntax THIS IS EXPERIMENTAL, USE AT YOUR OWN RISK"
- . #:reader read-one-wisp-sexp
- . #:compilers `((scheme . ,compile-scheme)) ; I do not touch quasiquotes yet.
+ ; . #:reader read-one-wisp-sexp
+ . #:reader wisp-scheme-read-chunk-env
+ . #:compilers `((scheme . ,compile-scheme)) ; this is scheme, not
+ ; wisp, because I do not
+ ; touch quasiquotes yet.
. #:decompilers `((scheme . ,decompile-scheme))
. #:evaluator : lambda (x module) : primitive-eval x
. #:printer write
diff --git a/wisp-scheme.w b/wisp-scheme.w
--- a/wisp-scheme.w
+++ b/wisp-scheme.w
@@ -48,11 +48,14 @@ define : line-code line
; literal values I need
define readcolon
string->symbol ":"
-define readdot
- string->symbol "."
+
+; define an intermediate dot replacement with UUID to avoid clashes.
+define dotrepr
+ string->symbol "DOTREPR-e749c73d-c826-47e2-a798-c16c13cb89dd"
+
define : line-continues? line
- equal? readdot : car : line-code line
+ equal? dotrepr : car : line-code line
define : line-only-colon? line
and
@@ -77,7 +80,7 @@ define : line-strip-continuation 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"
cdr line
define : indent-level-reduction indentation-levels level select-fun
@@ -117,120 +120,154 @@ define : wisp-scheme-read-chunk-lines po
currentindent 0
currentsymbols '()
emptylines 0
- let : : next-char : peek-char port
- cond
- : eof-object? next-char
- append indent-and-symbols : list : append (list currentindent) currentsymbols
- : <= 2 emptylines
- . indent-and-symbols
- : 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.
- : and inunderscoreindent : not : equal? #\space next-char
- throw 'wisp-syntax-error "initial underscores without following whitespace at beginning of the line after" : last indent-and-symbols
- : or (equal? #\newline next-char) (equal? #\return next-char)
- read-char port ; remove the newline
- ; TODO: Check whether when or if should be preferred here. guile 1.8 only has if.
- 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
- ; 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.
+ if : <= 2 emptylines ; 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
+ let : : next-char : peek-char port
+ cond
+ : eof-object? next-char
+ append indent-and-symbols : list : append (list currentindent) currentsymbols
+ : and inindent : equal? #\space next-char
+ read-char port ; remove char
loop
- append indent-and-symbols : list parsedline
+ . indent-and-symbols
. #t ; inindent
- equal? #\_ : peek-char port
+ . #f ; inunderscoreindent
. #f ; incomment
- . 0
- . '()
- if : line-empty? parsedline
- 1+ emptylines
+ 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.
+ : and inunderscoreindent : not : equal? #\space next-char
+ throw 'wisp-syntax-error "initial underscores without following whitespace at beginning of the line after" : last indent-and-symbols
+ : or (equal? #\newline next-char) ; (equal? #\return 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
+ ; 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
+ . #f ; incomment
. 0
- : 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) ; 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
- ; | which had a problem with the literal comment
- ; v 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.
- ; TODO: If used from Guile, activate curly infix via read-options.
- append currentsymbols : list : read port
- . emptylines
+ . '()
+ . 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
+ ; | which had a problem with the literal comment
+ ; v char.
+ : equal? (string-ref ";" 0) next-char
+ loop
+ . indent-and-symbols
+ . #f ; inindent
+ . #f ; inunderscoreindent
+ . #t ; incomment
+ . currentindent
+ . currentsymbols
+ . emptylines
+ : equal? (string-ref "." 0) next-char
+ ; TODO: special case for the dot using the dotrepr as
+ ; intermediate representation
+ read-char port ; remove next-char
+ let : : next-next-char : peek-char port
+ ; if we don’t need the special handling, add the
+ ; next char to the port again
+ if : not : or (equal? #\space next-next-char) (equal? #\newline next-next-char) (eof-object? next-next-char) (equal? #\return next-next-char)
+ unread-char next-char port
+ loop
+ . indent-and-symbols
+ . #f ; inindent
+ . #f ; inunderscoreindent
+ . #f ; incomment
+ . currentindent
+ ; this also takes care of the hashbang and leading comments.
+ append currentsymbols
+ ; if we don’t need the special handling, just
+ ; use the reader. Otherwise append the special
+ ; representation of the dot to avoid triggering
+ ; this for the dot escaped as |.| or #{.}#
+ if : not : or (equal? #\space next-next-char) (equal? #\newline next-next-char) (eof-object? next-next-char) (equal? #\return next-next-char)
+ list : read port
+ list dotrepr
+ . emptylines
+ ; TODO: finish
+ 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.
+ ; TODO: If used from Guile, activate curly infix via read-options.
+ append currentsymbols : list : read port
+ . emptylines
define : line-code-replace-inline-colons line
- ' "Replace inline colons by opening parens which close at the end of the 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 '()
@@ -394,7 +431,7 @@ define : wisp-scheme-indentation-to-pare
define : wisp-scheme-replace-inline-colons lines
- ' "Replace inline colons by opening parens which close at the end of the line"
+ . "Replace inline colons by opening parens which close at the end of the line"
let loop
: processed '()
unprocessed lines
@@ -406,7 +443,7 @@ define : wisp-scheme-replace-inline-colo
define : wisp-scheme-strip-indentation-markers lines
- ' "Strip the indentation markers from the beginning of the lines"
+ . "Strip the indentation markers from the beginning of the lines"
let loop
: processed '()
unprocessed lines
@@ -426,52 +463,52 @@ when it reads a dot. So we have to take
code to recreate the improper lists.
Match is awesome!"
- let
- :
- improper
- match code
- : a ... b '#{.}# c
- append (map wisp-make-improper a)
- cons (wisp-make-improper b) (wisp-make-improper c)
+ let
+ :
+ improper
+ match code
+ : a ... b 'DOTREPR-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
+ throw 'wisp-syntax-error (format #f "incorrect dot-syntax #{.}# in code: not a proper pair: ~A" li)
+ let check
+ : tocheck improper
+ match tocheck
+ ; lists with only one member
+ : 'DOTREPR-e749c73d-c826-47e2-a798-c16c13cb89dd
+ syntax-error tocheck
+ ; list with remaining dot.
: a ...
- map wisp-make-improper a
+ if : member dotrepr a
+ syntax-error tocheck
+ map check a
+ ; simple pair
+ : 'DOTREPR-e749c73d-c826-47e2-a798-c16c13cb89dd . c
+ syntax-error tocheck
+ ; simple pair, other way round
+ : a . 'DOTREPR-e749c73d-c826-47e2-a798-c16c13cb89dd
+ syntax-error tocheck
+ ; more complex pairs
+ : ? pair? a
+ let
+ : head : drop-right a 1
+ tail : last-pair a
+ cond
+ : equal? dotrepr : car tail
+ syntax-error tocheck
+ : equal? dotrepr : cdr tail
+ syntax-error tocheck
+ : member dotrepr head
+ syntax-error tocheck
+ else
+ . a
a
. a
- define : syntax-error li
- throw 'wisp-syntax-error (format #f "incorrect dot-syntax #{.}# in code: not a proper pair: ~A" li)
- let check
- : tocheck improper
- match tocheck
- ; lists with only one member
- : '#{.}#
- syntax-error tocheck
- ; list with remaining dot.
- : a ...
- if : member readdot a
- syntax-error tocheck
- map check a
- ; simple pair
- : '#{.}# . c
- syntax-error tocheck
- ; simple pair, other way round
- : a . '#{.}#
- syntax-error tocheck
- ; more complex pairs
- : ? pair? a
- let
- : head : drop-right a 1
- tail : last-pair a
- cond
- : equal? readdot : car tail
- syntax-error tocheck
- : equal? readdot : cdr tail
- syntax-error tocheck
- : member readdot head
- syntax-error tocheck
- else
- . a
- a
- . a
define : wisp-scheme-read-chunk port