(Arne Babenhauserheide)
2015-06-23: merge newbase60 and release. merge newbase60 and release.
diff --git a/.bugs/bugs b/.bugs/bugs --- a/.bugs/bugs +++ b/.bugs/bugs @@ -40,3 +40,4 @@ breaks on empty files wisp-scheme: breaks on lines with only underscores. These should be treated as empty lines. | owner:, open:False, id:e464b5ce49deb14a80f67d50c6d70043ca9bde25, time:1415124488.16 quote as only char in a line gets parenthized instead of becoming a paren-prefix. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:eb7468387e90bb5d13f5a5d81c6f4a704f2ca0fb, time:1390326369.6 in the REPL output can be delayed by one line: Appears only when submitting the next command. | owner:, open:False, id:f1e42bbd4c17a2dec886c26d9c14e770bcff66d2, time:1415972414.48 +wisp-scheme: parser problem with dotted pair: use-modules : (ice-9 popen) #:select ((open-input-pipe . oip)) | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:ff078cba853c1a2fdbd41cf0228ad7920a642c0d, time:1428358435.75 diff --git a/.hgsigs b/.hgsigs --- a/.hgsigs +++ b/.hgsigs @@ -18,3 +18,4 @@ eaf23f42b01382e4ab255abcd34e031b043e1f56 695e3f4ff4bd2512e2d963c5b21385415c3b6dc3 0 iJsEAAEIAAYFAlRb4xsACgkQ3M8NswvBBUiRugP41O3ZOBViEjB0y4smTiU/yju4b/xJczLBhbNM1ExKu/EB3oQkAPpZhnBQcOPz43TMl2Kk8QKJgFcgeHKQlT+ZyMxZ0j7/GOSBxTH2Q1x5SXwJlnJAdmSH7UE2i5btEsemjkqAuqOlkX+z7QIswFSv7yHoBVh/Qs9AvcY0cCKFYw== fed7f4d46a41b0814c81eb08dcdb506b38321c61 0 iQEcBAABAgAGBQJUbMOkAAoJEKMv031G/7TThsYIALXZAJY4Z4n5Be6mTE/CRXE7g3GlDEBPwstnvUBNzXiM5dAQbLHUt71yRx+d2WxxRHxUfuWG8PgrO/beITdjWhwoaM0fhknPRIOZ3Sc3RSrtleTm9gx1DS6CW5sCQvmqRSdyYJlqS30oHiq/gPftmFq2CllrSZWblL+t+/BfBLfG26DN4jy/b0IN5J1qeoi4gP/FwQ3e8A1lUIznjzQa57BVGBc/kKA+pAy/yFAlFvukAOG0BbFGRe0K3Gj6xITLdxfrmndH/688jgefUp+7JhLZZkfIoFAWBosPRQ5a2zaB1YRtUMEKgvvA05UiyTLQdlME2d52X1sSKrS9p69sTUU= 36b8c0daff2cd8cadb73b0dcc19c16a60f5b58eb 0 iJwEAAEIAAYFAlUKBPEACgkQ3M8NswvBBUgDugP8C6yJk7LyLOFMGoKLmnBin1dc9uuaj7idhx24tjgLjxLoM06I6QxkWPSEoKgVUR01Euu0EbXaoJogAaOUlaUTZPeSeSAZStvTmXveWL4P1VIQoERy1hmia+tMPxQKXkXf5R0YRwdmiqOh1AoH8dVdkCsCfplBc3VGrdDN4caZP00= +a8ea98c78d90ae3e1b4daaf4bab3e2a7a847a06f 0 iJwEAAEIAAYFAlUoSqEACgkQ3M8NswvBBUihJQP/XB8kHNEcsTj5pgBtMepmIX/3CmVaz6ZNgzhSzJSS1oz2DMbXPJh32QaDwRd5wCoNksD00ch7e9UWhTSZztI/yDY9KwZrTV/OIDFzIdfSsdDO4J0WNxHmgymHSfitCjHcgSvT/C9/mubhNECPrQQUx08FMnNiNvcmGpwVOwakNNw= diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -26,3 +26,4 @@ b7441736af4dc8f1a7df860d1b064e080a45e1a5 0e702c268e6fdc9c52f034b6553c940b09c16400 v0.8.0 8eaf023f5d3bc20ad4b795cde3a92e3b5c242dba v0.8.1 327acbae68ef4efbf77734f0ee20359ed559ce0d v0.8.2 +41c48043ca33bf47311a93d0545b13a0578c3cf0 v0.8.3 diff --git a/Changelog b/Changelog deleted file mode 100644 --- a/Changelog +++ /dev/null @@ -1,32 +0,0 @@ -0.3.1 - * wisp.py: parentheses in comments no longer break the parser - * wisp.py: inline " ' : " is turned into " '(" - * multithreaded-magic.w: New example: Easy multithreading. - * hello-world-server.w: Show local time instead of UTC and be a - bit more friendly. - -0.3 - * wisp-multiline.sh: started with emacs support. Not yet nice. - * wisp.w: renamed to wisp-guile.w to show that it uses guile - scheme. - * wisp.w: started wisp in wisp. Does not work, yet. - * hello-world-server.w: First actually running example code. - * wisp-multiline.sh: directly execute the typed script in guile - scheme. Robust shell-script commandline parsing. - * Readme.txt: Note the license and add references and footnotes. - * Readme.txt: Fix the examples and add a stdin-example with guile. - -0.2 - * wisp.py: got more resilient. - * wisp.py: condense multiple inline : into multiple brackets - without whitespace. - * wisp.py: refactored into multiple distinct phases for easier - maintainability. - * wisp.py: allow escaping : and _ with \. - * wisp.py: added websafe indent with _ - * wisp.py: a colon at the end of the line is interpreted as () - * wisp.py: don’t interpret wisp code in brackets or strings. - -0.1 - * wisp.py: first version. - * Readme.txt: Added a readme. diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +wisp 0.8.3 (2015-04-10): +- add partial source-properties support: show line numbers in backtraces. +- d20world: start of experiement to plot the results. + wisp 0.8.2 (2015-03-18): - resolve REPL delayed output bug. - forbid dot at the end of a line and as only symbol in a line to reserve them for future use. 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.8.2], +AC_INIT([wisp], [0.8.3], [arne_bab@web.de]) # Check for programs I need for my build AC_CANONICAL_TARGET diff --git a/examples/cli.w b/examples/cli.w new file mode 100755 --- /dev/null +++ b/examples/cli.w @@ -0,0 +1,15 @@ +#!/usr/bin/env sh +exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples cli) main)' -s "$0" "$@" +; !# + +define-module : examples cli + . #:use-module : ice-9 match + +define : main args + match args + : prog ; just the program name, empty call + display args + newline + +main '("foo") + diff --git a/examples/newbase60.w b/examples/newbase60.w new file mode 100755 --- /dev/null +++ b/examples/newbase60.w @@ -0,0 +1,149 @@ +#!/usr/bin/env sh +# -*- wisp -*- +exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples newbase60) main)' -s "$0" "$@" +; !# + +;; Encoding and decoding numbers in New Base 60 as defined by Tantek: +;; http://tantek.pbworks.com/NewBase60 + +;; Based on the very elegant implementation from Kevin Marks licensed under CC0: +;; https://github.com/indieweb/newBase60py/blob/master/newbase60.py + +define-module : examples newbase60 + . #:export : integer->sxg sxg->integer date->sxg sxg->date date->sxgepochdays sxgepochdays->yeardays yeardays->sxgepochdays + . #:use-module : srfi srfi-1 + +define base60letters "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghijkmnopqrstuvwxyz" +define base60numbers + append + map cons (string->list base60letters) : iota : string-length base60letters + quote + : #\l . 1 ; typo lowercase l to 1 + #\I . 1 ; typo capital I to 1 + #\O . 0 ; typo capital O to 0 + +define : positive-integer->sxg num + . "Convert a positive integer to Tanteks new base 60." + if : equal? 0 num + . "0" + let loop + : s '() + n num + if : equal? n 0 + list->string s + loop + cons (string-ref base60letters (remainder n 60)) s + quotient n 60 + +define : positive-sxg->integer string + . "Convert a positive new base 60 string into a positive integer." + let loop + : n 0 + s string + cond + : equal? "" s + . n + else + loop + + : assoc-ref base60numbers : string-ref s 0 + * n 60 + string-drop s 1 + +define : integer->sxg num + . "Convert an integer to Tanteks new base 60." + if : >= num 0 + positive-integer->sxg num + string-append "-" : positive-integer->sxg : - num + +define : sxg->integer str + . "Convert a new base 60 string into an integer." + if : and (>= (string-length str) 1) (equal? #\- (string-ref str 0)) + - : positive-sxg->integer : string-drop str 1 + positive-sxg->integer str + +define : date->sxgepochdays year month day hour minute second + let + : tm : gmtime 0 ; initialize + set-tm:year tm : - year 1900 + set-tm:mon tm month + set-tm:mday tm day + set-tm:hour tm hour + set-tm:min tm minute + set-tm:sec tm second + let* + : epochseconds : car : mktime tm "+0" ; 0: UTC + epochdays : quotient epochseconds : * 24 60 60 + integer->sxg epochdays + +define : yeardays->sxgepochdays year yeardays + let + : tm : car : strptime "%Y %j" : string-join : map number->string : list year yeardays + let* + : epochseconds : car : mktime tm "+0" ; 0: UTC + epochdays : quotient epochseconds : * 24 60 60 + integer->sxg epochdays + +define : sxgepochdays->yeardays str + . "Turn sexagesimal days since epoch into year (YYYY) and day of year (DDD)." + let* + : epochdays : sxg->integer str + epochseconds : * epochdays 24 60 60 + tm : gmtime epochseconds + year : + 1900 : tm:year tm + yeardays : tm:yday tm + list year (+ yeardays 1) + +define : date->sxg year month day hour minute second + . "Convert a date into new base 60 format: + yyyymmdd hhmmss -> YYMD-hms (can extend till 3599) + " + format #f "~A-~A" + apply string-append + map integer->sxg + list year month day + apply string-append + map integer->sxg + list hour minute second + +define : sxg->date str + . "Convert a new base 60 date into a list: + YYMD-hms -> (year month day hour minute second) + " + let* + : centeridx : string-rindex str #\- ; rindex because the year could be negative + getstr : lambda (s di) : string : string-ref str : + centeridx di + let + : year : substring/read-only str 0 : - centeridx 2 + month : getstr str -2 + day : getstr str -1 + hour : getstr str 1 + minute : getstr str 2 + second : getstr str 3 + map sxg->integer + list year month day hour minute second + +define : main args + let + : help : lambda () : format #t "usage: ~A [integer | -d string | --datetime | --datetime year month day hour minute second | --help]\n" : list-ref args 0 + cond + : or (= 1 (length args)) (member "--help" args) + help + : and (= 8 (length args)) : equal? "--datetime" : list-ref args 1 + format #t "~A\n" : apply date->sxg : map string->number : drop args 2 + : and (= 8 (length args)) : equal? "--sxgepochdays" : list-ref args 1 + format #t "~A\n" : apply date->sxgepochdays : map string->number : drop args 2 + : and (= 4 (length args)) : equal? "--sxgepochdays-from-yearday" : list-ref args 1 + format #t "~A\n" : apply yeardays->sxgepochdays : map string->number : drop args 2 + : and (= 2 (length args)) : equal? "--datetime" : list-ref args 1 + let : : tm : localtime : current-time + format #t "~A\n" : apply date->sxg : list (+ 1900 (tm:year tm)) (+ 1 (tm:mon tm)) (tm:mday tm) (tm:hour tm) (tm:min tm) (tm:sec tm) + : and (= 3 (length args)) : equal? "--decode-datetime" : list-ref args 1 + format #t "~A\n" : sxg->date : list-ref args 2 + : and (= 3 (length args)) : equal? "--decode-sxgepochdays" : list-ref args 1 + format #t "~A\n" : sxgepochdays->yeardays : list-ref args 2 + : and (= 3 (length args)) : equal? "-d" : list-ref args 1 + format #t "~A\n" : sxg->integer : list-ref args 2 + : = 2 : length args + format #t "~A\n" : integer->sxg : string->number : list-ref args 1 + else + help diff --git a/guildhall-packages/newbase60.scm b/guildhall-packages/newbase60.scm new file mode 100644 --- /dev/null +++ b/guildhall-packages/newbase60.scm @@ -0,0 +1,151 @@ +#!/usr/bin/env sh +# -*- scheme -*- +exec guile -e '(@@ (examples newbase60) main)' -s "$0" "$@" +; !# + +;; Encoding and decoding numbers in New Base 60 as defined by Tantek: +;; http://tantek.pbworks.com/NewBase60 + +;; Based on the very elegant implementation from Kevin Marks licensed under CC0: +;; https://github.com/indieweb/newBase60py/blob/master/newbase60.py + +(define-module (examples newbase60) + #:export (integer->sxg sxg->integer date->sxg sxg->date date->sxgepochdays sxgepochdays->yeardays yeardays->sxgepochdays) + #:use-module (srfi srfi-1)) + +(define base60letters "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghijkmnopqrstuvwxyz") +(define base60numbers + (append + (map cons (string->list base60letters) (iota (string-length base60letters))) + (quote + ((#\l . 1 ); typo lowercase l to 1 + (#\I . 1 ); typo capital I to 1 + (#\O . 0 ))))); typo capital O to 0 + +(define (positive-integer->sxg num) + "Convert a positive integer to Tanteks new base 60." + (if (equal? 0 num) + "0" + (let loop + ((s '()) + (n num)) + (if (equal? n 0) + (list->string s) + (loop + (cons (string-ref base60letters (remainder n 60)) s) + (quotient n 60)))))) + +(define (positive-sxg->integer string) + "Convert a positive new base 60 string into a positive integer." + (let loop + ((n 0) + (s string)) + (cond + ((equal? "" s) + n) + (else + (loop + (+ (assoc-ref base60numbers (string-ref s 0)) + (* n 60)) + (string-drop s 1)))))) + +(define (integer->sxg num) + "Convert an integer to Tanteks new base 60." + (if (>= num 0) + (positive-integer->sxg num) + (string-append "-" (positive-integer->sxg (- num))))) + +(define (sxg->integer str) + "Convert a new base 60 string into an integer." + (if (and (>= (string-length str) 1) (equal? #\- (string-ref str 0))) + (- (positive-sxg->integer (string-drop str 1))) + (positive-sxg->integer str))) + +(define (date->sxgepochdays year month day hour minute second) + (let + ((tm (gmtime 0 ))); initialize + (set-tm:year tm (- year 1900)) + (set-tm:mon tm month) + (set-tm:mday tm day) + (set-tm:hour tm hour) + (set-tm:min tm minute) + (set-tm:sec tm second) + (let* + ((epochseconds (car (mktime tm "+0" ))); 0: UTC + (epochdays (quotient epochseconds (* 24 60 60)))) + (integer->sxg epochdays)))) + +(define (yeardays->sxgepochdays year yeardays) + (let + ((tm (car (strptime "%Y %j" (string-join (map number->string (list year yeardays))))))) + (let* + ((epochseconds (car (mktime tm "+0" ))); 0: UTC + (epochdays (quotient epochseconds (* 24 60 60)))) + (integer->sxg epochdays)))) + +(define (sxgepochdays->yeardays str) + "Turn sexagesimal days since epoch into year (YYYY) and day of year (DDD)." + (let* + ((epochdays (sxg->integer str)) + (epochseconds (* epochdays 24 60 60)) + (tm (gmtime epochseconds)) + (year (+ 1900 (tm:year tm))) + (yeardays (tm:yday tm))) + (list year (+ yeardays 1)))) + +(define (date->sxg year month day hour minute second) + "Convert a date into new base 60 format: + yyyymmdd hhmmss -> YYMD-hms (can extend till 3599) + " + (format #f "~A-~A" + (apply string-append + (map integer->sxg + (list year month day))) + (apply string-append + (map integer->sxg + (list hour minute second))))) + +(define (sxg->date str) + "Convert a new base 60 date into a list: + YYMD-hms -> (year month day hour minute second) + " + (let* + ((centeridx (string-rindex str #\- )); rindex because the year could be negative + (getstr (lambda (s di) (string (string-ref str (+ centeridx di)))))) + (let + ((year (substring/read-only str 0 (- centeridx 2))) + (month (getstr str -2)) + (day (getstr str -1)) + (hour (getstr str 1)) + (minute (getstr str 2)) + (second (getstr str 3))) + (map sxg->integer + (list year month day hour minute second))))) + +(define (main args) + (let + ((help (lambda () (format #t "usage: ~A [integer | -d string | --datetime | --datetime year month day hour minute second | --help]\n" (list-ref args 0))))) + (cond + ((or (= 1 (length args)) (member "--help" args)) + (help)) + ((and (= 8 (length args)) (equal? "--datetime" (list-ref args 1))) + (format #t "~A\n" (apply date->sxg (map string->number (drop args 2))))) + ((and (= 8 (length args)) (equal? "--sxgepochdays" (list-ref args 1))) + (format #t "~A\n" (apply date->sxgepochdays (map string->number (drop args 2))))) + ((and (= 4 (length args)) (equal? "--sxgepochdays-from-yearday" (list-ref args 1))) + (format #t "~A\n" (apply yeardays->sxgepochdays (map string->number (drop args 2))))) + ((and (= 2 (length args)) (equal? "--datetime" (list-ref args 1))) + (let ((tm (localtime (current-time)))) + (format #t "~A\n" (apply date->sxg (list (+ 1900 (tm:year tm)) (+ 1 (tm:mon tm)) (tm:mday tm) (tm:hour tm) (tm:min tm) (tm:sec tm)))))) + ((and (= 3 (length args)) (equal? "--decode-datetime" (list-ref args 1))) + (format #t "~A\n" (sxg->date (list-ref args 2)))) + ((and (= 3 (length args)) (equal? "--decode-sxgepochdays" (list-ref args 1))) + (format #t "~A\n" (sxgepochdays->yeardays (list-ref args 2)))) + ((and (= 3 (length args)) (equal? "-d" (list-ref args 1))) + (format #t "~A\n" (sxg->integer (list-ref args 2)))) + ((= 2 (length args)) + (format #t "~A\n" (integer->sxg (string->number (list-ref args 1))))) + (else + (help))))) + + diff --git a/guildhall-packages/pkg-list.scm b/guildhall-packages/pkg-list.scm new file mode 100644 --- /dev/null +++ b/guildhall-packages/pkg-list.scm @@ -0,0 +1,6 @@ +(package (newbase60 (0)) + (synopsis "Implementation of Tanteks New Base 60") + (libraries + (scm -> "newbase60")) + (programs + (("newbase60.scm") -> "newbase60"))) diff --git a/tests/dotted-pair.scm b/tests/dotted-pair.scm new file mode 100644 --- /dev/null +++ b/tests/dotted-pair.scm @@ -0,0 +1,3 @@ +(use-modules ((ice-9 popen) #:select ((open-input-pipe . oip)))) + + diff --git a/tests/dotted-pair.w b/tests/dotted-pair.w new file mode 100644 --- /dev/null +++ b/tests/dotted-pair.w @@ -0,0 +1,1 @@ +use-modules : (ice-9 popen) #:select ((open-input-pipe . oip)) diff --git a/wisp-mode.el b/wisp-mode.el --- a/wisp-mode.el +++ b/wisp-mode.el @@ -49,6 +49,10 @@ ; use this mode automatically ;;;###autoload (add-to-list 'auto-mode-alist '("\\.w\\'" . wisp-mode)) +;;;###autoload +(add-hook 'wisp-mode-hook + (lambda () + (electric-indent-local-mode -1))) ; see http://www.emacswiki.org/emacs/DerivedMode diff --git a/wisp-scheme.w b/wisp-scheme.w --- a/wisp-scheme.w +++ b/wisp-scheme.w @@ -380,7 +380,11 @@ define : line-finalize line line-strip-lone-colon line-strip-continuation line when : not : null? : source-properties line - set-source-properties! l : 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 @@ -400,6 +404,10 @@ define : wisp-propagate-source-propertie 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