(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