(Arne Babenhauserheide)
2015-07-31: merge with evolve improvements merge with evolve improvements
diff --git a/.bugs/bugs b/.bugs/bugs --- a/.bugs/bugs +++ b/.bugs/bugs @@ -1,4 +1,5 @@ testsuite: to pass, the tree-il has to match, not the emitted string. This allows for reader-only implementations. | owner:, open:False, id:00b74a730bbf076e73166e817ca7b0a273b376d4, time:1408224636.42 +wisp-scheme: backtraces should show the wisp source. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:0475df81a594a52d171a1b811752ca64e5a71df5, time:1426792099.58 wisp-scheme: unescape \_ and \: | owner:, open:False, id:086f61a06e16f1ef56e9917453bbd55b5879d15d, time:1415121255.99 fails when I add stuff at the end of end of example.w | owner:, open:False, id:08c68e1ce0c9798184c01806d2661a3220bff3cd, time:1363789693.79 wisp-mode in quoted lists only the first item is colorized as data, but all words up to the last paren should be colorized. | owner:, open:True, id:1675ca3f894ed8470fa292149a476a2fa0d17140, time:1397196957.45 @@ -6,13 +7,15 @@ add a testsuite for wisp parsers. wisp-mode: export wisp to html fails in org-mode: font-lock-fontify-keywords-region: Invalid regexp | owner:, open:False, id:1e46d8c05580c961c37a32d36c987a5dd1d34943, time:1389371020.39 an empty line with : should start with double parens | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:2e188ddf44d36e4605030d3c58607ebfa97d189e, time:1390328674.43 wisp-in-wisp: remove the leading . for continuation lines after inferring the brackets. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:2e42e5b64622f0cc383eb8acc3d510912e925bf0, time:1377476687.79 +interpret ` , : correctly. | owner:, open:True, id:2feb5f048b55274c1bc7c8168c8cb358c0c8dd1d, time:1426777900.6 '() gives REPR-QUOTE-... | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:30c42de75c137f483245898e2a62af1e65cf19a6, time:1415060388.34 multiple escaped initial underscores must be unescaped. | owner:, open:True, id:314e45488da4c7c8298c4c64ece03359918d057b, time:1415959749.14 wisp: handle general paren prefixes like quote, quasiquote, etc. | owner:, open:False, id:323ff94b5be635742619467e1cb44f4c0d96f63f, time:1379047798.47 throw an exception when reducing indentation to an unknown indentation level. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:424186bd85f186b7279c5c59e2bd42f847284719, time:1376003568.91 +LANG=C breaks bootstrap: python encoding error: it uses ascii. | owner:, open:True, id:43c7461bfb6f35a90ff3f4497c8232e2457ce1c7, time:1427819877.7 wisp-in-wisp: only parses the first 272 lines, for some reason. | owner:, open:False, id:4cb6c556d7136609e2da9ab3fc045a39847f1ef3, time:1377014682.98 adjust runtests.sh to use testrunner.w | owner:, open:False, id:4d4e76343fe09f0ec72a3e5eb0077bd16e12f9d5, time:1415127234.43 -wisp-scheme: REPL: sometimes the output of a command is only shown after typing the next non-empty line. | owner:, open:True, id:56d2f81e9c89accb0b0bc668ddc8feed3b60e9b2, time:1416584789.23 +wisp-scheme: REPL: sometimes the output of a command is only shown after typing the next non-empty line. | owner:, open:False, id:56d2f81e9c89accb0b0bc668ddc8feed3b60e9b2, time:1416584789.23 implement wisp in wisp | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:6299306916706410702029289bf32edab1e7f17c, time:1367113341.49 support other types of brackets, like square brackets. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:6749f3abcb9455eac9271efd8265797bce114239, time:1389134151.98 linebreaks in parens still break | owner:, open:False, id:6797987c7834a53358fb4ebbd8b9b36c2c4a8f01, time:1379004764.14 @@ -20,7 +23,7 @@ wisp-guile.w does not yet remove the lea inline ' : should be '( | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:72d534a8b23b4cb168017f1bb7d8816f0ea170c4, time:1366497335.26 failing test tests/shebang.w | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:74a851f83af8996465a7b24d8453161beb0f0fd5, time:1379106761.57 non-nested multiline comments with #! !#. Requires restructuring. | owner:, open:False, id:7a57614fa920b2ddad002d044b144d0bb7c34f84, time:1389364108.01 -wisp-scheme: interpret , : as ,() similar to : , | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:85e150dcb10c49d8f51db525e07d24e83bdba0f1, time:1416432201.21 +wisp-scheme: interpret , : as ,() similar to : , | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:85e150dcb10c49d8f51db525e07d24e83bdba0f1, time:1416432201.21 wisp-guile: support nested multi-line comments with #| ... |#: multiline comments (srfi-30). Requires restructuring. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:8cf6202873d4454f57813dd17cf60432059f7c62, time:1389569421.6 wisp-scheme: Does not recognize the . #!curly-infix request for curly-infix or other reader syntax. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:91f27adb7d4e378e034b3408b6e4616f707f9587, time:1418162368.88 wisp-guile: the repl does not require 3 returns when you use a single char as function, or rather only does so every second time | owner:, open:True, id:9cedd0bdbf4a3b17add4bfe86ad5a23e500cfc6c, time:1379064870.78 @@ -36,4 +39,5 @@ comments containing a closing parenthesi breaks on empty files | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:e40fa7a93eb2c497dca1af7eed22ad5ed5cfbe7f, time:1390325470.91 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:True, id:f1e42bbd4c17a2dec886c26d9c14e770bcff66d2, time:1415972414.48 +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 @@ -17,3 +17,7 @@ 32659321b29470b5198827eda494d9824cc161ee eaf23f42b01382e4ab255abcd34e031b043e1f56 0 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 diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -25,3 +25,8 @@ 42ab97d010efa7883240f5e5254ea46fd9423239 b7441736af4dc8f1a7df860d1b064e080a45e1a5 v0.6.6 0e702c268e6fdc9c52f034b6553c940b09c16400 v0.8.0 8eaf023f5d3bc20ad4b795cde3a92e3b5c242dba v0.8.1 +327acbae68ef4efbf77734f0ee20359ed559ce0d v0.8.2 +41c48043ca33bf47311a93d0545b13a0578c3cf0 v0.8.3 +a4bca2a0f2f6659d97b1db471ae9803119b80529 v0.8.4 +f0096bf5f3baee5017be94f49c70515fe2a535b3 wisp-mode-0.2.1 +fb551bbe7084d22ef0c8e35df3864eb2aef46005 v0.8.5 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,39 @@ +wisp 0.8.5 (2015-07-28): +- wisp-scheme.w now parses : . to nothing. The colon adds parens, the + dot removes them. This provides compatibility to the older parser. +- wisp is now SRFI-119: http://srfi.schemers.org/srfi-119/srfi-119.html + +wisp 0.8.4 (2015-06-23): +- no longer wrap wisp blocks into begin. Fixes missing macro + definitions when executed as file. +- any top-level form ends a wisp block. Required to avoid wrapping in + begin. In the REPL code is now executed when entering the first line + of the next top-level form. +- new examples: newbase60 and cli. +- known issue: To execute a procedure with shell-indirection, you have + to define a module. +- wisp-mode: disable electric-indent-mode which reindented lines + wrongly when pressing enter. + +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. +- generalized the shell-call to guile: It gets the parentdir from $0. +- note curly braces, neoteric expressions and dual-wisp-sweet syntax. +- added tests: sxml, self-referencial function, curly-infix. +- new example: beautiful factorial. +- new example: ensemble estimation with ensemble square root filter. Uses python driven by an output-pipe as a plotting tool. +- SRFI 119 in draft. + +wisp 0.8.1 (2014-11-19): +- srfi: polish implementation notes. +- add the requirements to the syntax-examples. +- wisp-scheme.w works completely again. + wisp 0.8.0 (2014-11-03): - the testsuite is defined in terms of the code-tree, not in terms of the readable file. Implemented in testrunner.w 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.1], +AC_INIT([wisp], [0.8.5], [arne_bab@web.de]) # Check for programs I need for my build AC_CANONICAL_TARGET diff --git a/docs/srfi-from-template.html b/docs/srfi-from-template.html --- a/docs/srfi-from-template.html +++ b/docs/srfi-from-template.html @@ -1,7 +1,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <html> <head> - <title>SRFI ?: wisp: simpler indentation-sensitive scheme</title> + <title>SRFI 119: wisp: simpler indentation-sensitive scheme</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> @@ -12,11 +12,31 @@ wisp: simpler indentation-sensitive sche <H1>Author</H1> -<ul> -<li>Arne Babenhauserheide -</li> +Arne Babenhauserheide + +<H1>Status</H1> + +<p> +This SRFI is currently in ``draft'' status. +To see an explanation of +each status that a SRFI can hold, see <a +href="http://srfi.schemers.org/srfi-process.html">here</a>. + +To provide input on this SRFI, please +<a href="mailto:srfi minus 119 at srfi dot schemers dot org">mail to +<code><srfi minus 119 at srfi dot schemers dot org></code></a>. See +<a href="../srfi-list-subscribe.html">instructions here</a> to +subscribe to the list. You can access previous messages via +<a href="mail-archive/maillist.html">the archive of the mailing list</a>. +</p><ul> + <li>Received: <a + href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-119/srfi-119.html?rev=1.1">2015/01/25</a></li> + <li>Draft: 2015/02/03-2015/04/03</li> + <li>Revised: <a + href="http://srfi.schemers.org/cgi-bin/viewcvs.cgi/*checkout*/srfi/srfi-119/srfi-119.html?rev=1.2">2015/06/23</a></li> </ul> + <h3>Acknowledgments</h3> <ul> <li>Thanks for many constructive discussions goes to Alan Manuel K. Gloria and David A. Wheeler. @@ -40,27 +60,33 @@ It resolves a limitation of <a href="htt </p> <p> -Wisp expressions can include any s-expressions and as such provide backwards compatibility. +Wisp expressions can include arbitrary s-expressions and as such provide backwards compatibility. </p> +<blockquote> <table><tr><th>wisp</th><th>s-exp</th></tr><tr><td> -<pre><b>define</b> : <i>hello</i> who - <i>format</i> #t "~A ~A!\n" - . "Hello" who -<i>hello</i> "Wisp" +<pre> +<b>define</b> : <i>factorial</i> n +__ <b>if</b> : <i>zero?</i> n +____ . 1 +____ <i>*</i> n : <i>factorial</i> (- n 1) + +<i>display</i> : <i>factorial</i> 5 +<i>newline</i> </pre> +</blockqote> </td><td> -<pre>(<b>define</b> (<i>hello</i> who) - (<i>format</i> #t "~A ~A!\n" - "Hello" who)) -(<i>hello</i> "S-exp") +<pre> +(<b>define</b> (<i>factorial</i> n) + (<b>if</b> (<i>zero?</i> n) + 1 + (<i>*</i> n (<i>factorial</i> (- n 1))))) + +(<i>display</i> (<i>factorial</i> 5)) +(<i>newline</i>) </pre> </td></tr></table> - -<H1>Issues</H1> - -<ul> -<li>wisp-scheme: REPL: sometimes the output of a command is only shown after typing the next non-empty line.</li></ul> +</blockquote> <H1>Rationale</H1> @@ -115,7 +141,7 @@ Wisp expressions can include any s-expre <h2>Wisp example</h2> -Since an example speaks more than a hundred explanations, the following shows wisp exploiting all its features - including curly-infix from <a href="http://srfi.schemers.org/srfi-105/srfi-105.html">SRFI 105</a>: +Since an example speaks more than a hundred explanations, the following shows wisp exploiting all its features - including compatibility with curly-infix from <a href="http://srfi.schemers.org/srfi-105/srfi-105.html">SRFI 105</a>: <blockquote> <pre> @@ -485,6 +511,12 @@ Effectively code in parentheses and stri <li>The suggested suffix for files using wisp-syntax is <code>.w</code>. +<li>To represent tail notation like <code>(define (foo . args))</code>, either avoid a linebreak before the dot as in <code>define : foo . args</code> or use a double dot to start the line: <code>. . args</code>. The first dot mark the line as continuation, the second enters the scheme code.</li> + +<li>A dot as symbol at the end of a line is reserved for potential future use. It should be a syntax error if the next non-empty line starts with non-zero indentation. A lone dot at the end of a line calls for hard to catch errors.</li> + +<li>A dot as only symbol in a line has no useful meaning: the line is by definition empty. As such, a dot as only symbol on a line is also reserved for future use and should be treated as a syntax error to avoid locking out future possibilities.</li> + </ul> @@ -723,10 +755,10 @@ FROM, OUT OF OR IN CONNECTION WITH THE S DEALINGS IN THE SOFTWARE. <hr> - <address>Editor: <a href="mailto:srfi-editors at srfi dot schemers dot org">Dave Mason</a></address> + <address>Editor: <a href="mailto:srfi-editors at srfi dot schemers dot org">Michael Sperber</a></address> <!-- Created: Tue Sep 29 19:20:08 EDT 1998 --> <!-- hhmts start --> -Last modified: Sun Jan 28 14:21:14 MET 2007 +Last modified: Thu Mar 12 08:52:43 MET 2015 <!-- hhmts end --> </body> </html> diff --git a/examples/cli.w b/examples/cli.w new file mode 100755 --- /dev/null +++ b/examples/cli.w @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +# -*- wisp -*- +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 : car args + else + display args + newline + diff --git a/examples/d20world.w b/examples/d20world.w --- a/examples/d20world.w +++ b/examples/d20world.w @@ -17,6 +17,9 @@ define-module : examples d20world . #:export : world neighbors d20-as-text d20-diffuse use-modules : ice-9 format +use-modules + : ice-9 popen + . #:select : open-output-pipe close-pipe define world : make-vector 20 0 define neighbors : make-vector 20 @@ -211,6 +214,7 @@ define : latlon2cellidx lat lon display : d20-as-text world newline + format #t "Diffuse ~A\n" 0.01 d20-diffuse world neighbors 0.01 display : d20-as-text world @@ -282,3 +286,52 @@ let loop : : steps 1000 loop : 1- steps display : d20-as-text world newline + +; now plot the result +let : : port : open-output-pipe "python" + format port "from mpl_toolkits.mplot3d import Axes3D, art3d +import numpy as np +import scipy as sp +from matplotlib import cm +import matplotlib.pyplot as plt +from scipy.spatial import Delaunay + +def Icosahedron(): + h = 0.5*(1+np.sqrt(5)) + p1 = np.array([[0,1,h],[0,1,-h],[0,-1,h],[0,-1,-h]]) + p2 = p1[:,[1,2,0]] + p3 = p1[:,[2,0,1]] + return np.vstack((p1,p2,p3)) + +Ico = Icosahedron() +tri = Delaunay(Ico) +CH = tri.convex_hull +points = tri.points + +fig = plt.figure(figsize=(4.0,4.0)) +ax = fig.add_subplot(111, projection='3d') + +print points +for i in range(points.shape[0]): + neighbors = tri.neighbors[i,:] + for n in range(points.shape[0]): + pts = [] + for u in range(points.shape[0]): + pt = np.zeros((3,3)) + pt[0,:] = points[(i),:] + pt[1,:] = points[(n),:] + pt[2,:] = points[(u),:] + # print pt + pt *= 0.5 + pt += 0.5 + pts.append(pt) + tr = art3d.Poly3DCollection(pts) + tr.set_color([(0.9*i)/points.shape[0]] + [(0.9*n)/points.shape[0]]*3) + ax.add_collection3d(tr) +# ax.plot_surface(x, y, z, color='g') + +plt.show() + +exit()\n" + close-pipe port + diff --git a/examples/d6.w b/examples/d6.w --- a/examples/d6.w +++ b/examples/d6.w @@ -2,7 +2,7 @@ ; !# define-module : examples d6 - . #:export : roll check + . #:export : roll check ; basic d6 rules, implemented in guile @@ -23,3 +23,5 @@ define : check skill target effect-thres display : check 12 9 3 newline display : roll + + diff --git a/examples/ensemble-estimation.w b/examples/ensemble-estimation.w --- a/examples/ensemble-estimation.w +++ b/examples/ensemble-estimation.w @@ -1,4 +1,5 @@ #!/usr/bin/env sh +# -*- wisp -*- exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples ensemble-estimation) main)' -s "$0" "$@" ; !# diff --git a/examples/evolve.w b/examples/evolve.w --- a/examples/evolve.w +++ b/examples/evolve.w @@ -1,4 +1,5 @@ #!/usr/bin/env sh +# -*- wisp -*- exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples evolve) main)' -s "$0" "$@" ; !# @@ -8,10 +9,9 @@ exec guile -L $(dirname $(dirname $(real ; NOTE: This only works after preprocessing to scheme. -; run via -; PATH=../guile-2.0.11/meta:$PATH GUILE_LOAD_PATH=. ./wisp-multiline.sh examples/evolve.w +define-module : examples evolve + . #:export : main -define-module : examples evolve ; Get the eval string which allows for selecting the language. use-modules : ice-9 eval-string @@ -145,7 +145,7 @@ define : evolution initialstring steps evolution-step string -define : run +define : main args ; firstoff, seed the random number generator! set! *random-state* : random-state-from-platform let diff --git a/examples/factorial.w b/examples/factorial.w new file mode 100755 --- /dev/null +++ b/examples/factorial.w @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples factorial) main)' -s "$0" "$@" +; !# + +define-module : examples factorial + . #:export : factorial + +define : factorial n ; (define (factorial n) + if : zero? n ; (if (zero? n) + . n ; => n + * n : factorial {n - 1} ; (* n (factorial {n - 1})))) + +define : main args + display : factorial 5 + newline + diff --git a/examples/fizzbuzz.w b/examples/fizzbuzz.w --- a/examples/fizzbuzz.w +++ b/examples/fizzbuzz.w @@ -9,16 +9,18 @@ define : divisible? number divisor = 0 : remainder number divisor define : fizzbuzz - let : : print_number #f - loop : : for i : up-from 1 : to 100 - set! print_number #t - when : divisible? i 3 - display "Fizz" - set! print_number #f - when : divisible? i 5 - display "Buzz" - set! print_number #f; - when print_number : display i - newline + let + : print_number #f + loop + : for i : up-from 1 : to 100 + set! print_number #t + when : divisible? i 3 + display "Fizz" + set! print_number #f + when : divisible? i 5 + display "Buzz" + set! print_number #f; + when print_number : display i + newline fizzbuzz diff --git a/examples/kit-encode.w b/examples/kit-encode.w --- a/examples/kit-encode.w +++ b/examples/kit-encode.w @@ -1,6 +1,10 @@ -#!./wisp-multiline.sh +#!/usr/bin/env sh +# -*- wisp -*- +exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples kit-encode) main)' -s "$0" "$@" ; !# +define-module : examples kit-encode + . #:export : main kittify kittifylarge unkittify kittyfile kittytextfile unkittyfile unkittytextfile use-modules srfi srfi-1 rnrs io ports @@ -257,55 +261,52 @@ define : unkittytextfile filepath ; displaywithnewline : kittyfile ".hg/store/00changelog.i" ; displaywithnewline : unkittytextfile "1.kit" -; Now for the ultimate Kittyfication - -displaywithnewline " - === TEXT MODE ===" - -displaywithnewline : kittify : map shiftbytedownfortext : bytevector->u8-list : string->utf8 "Karlsruhe Institut für Technologie (KIT)" - -displaywithnewline : utf8->string : u8-list->bytevector : map shiftbyteupfortext : unkittify " - A.Y .p.i .q.p .s.e .b.3i.8. - k.q .r. f.r. s.r. 3i.c.2A. - 23.p .3 i.K.b._ .e.k .m.i - .m.d .f .b.3i.3 r.A. 8.K. -3s.. .... . .... .... .... -.............. .... .... .... -Karlsruher Institut fuer Technologie -" - - -displaywithnewline " - - === BINARY MODE ===" - -displaywithnewline : kittify : bytevector->u8-list : string->utf8 "Karlsruhe Institut für Technologie (KIT)" - -displaywithnewline : utf8->string : u8-list->bytevector : unkittify " - 1F. 1c.1 u.1o .1v. 1u.1x.1j - .1g .Y. 1D.1 q.1v .1w.1k.1 - w.1x .1 w.Y.1h. 3F.3 8.1u - .Y.1 Q. 1g.1e.1 j.1q .1r. -1o.1 r.1i . 1k.1 g.Y. f.1F -.1D.1Q.g...... .... .... .... -Karlsruher Institut fuer Technologie -" - - -displaywithnewline " - - === KIT, IMK, RemoteC ===" - -displaywithnewline : kittify : map shiftbytedownfortext : bytevector->u8-list : string->utf8 "Karlsruhe Institut für Technologie (KIT), IMK-ASF, RemoteC" - - -displaywithnewline " - - === kittifyscript ===" - -displaywithnewline : kittytextfile "examples/kit-encode.w" - - - +define : main args + . "The ultimate Kittyfication" + displaywithnewline " + === TEXT MODE ===" + + displaywithnewline : kittify : map shiftbytedownfortext : bytevector->u8-list : string->utf8 "Karlsruhe Institut für Technologie (KIT)" + + displaywithnewline : utf8->string : u8-list->bytevector : map shiftbyteupfortext : unkittify " + A.Y .p.i .q.p .s.e .b.3i.8. + k.q .r. f.r. s.r. 3i.c.2A. + 23.p .3 i.K.b._ .e.k .m.i + .m.d .f .b.3i.3 r.A. 8.K. + 3s.. .... . .... .... .... + .............. .... .... .... + Karlsruher Institut fuer Technologie + " + + displaywithnewline " + + === BINARY MODE ===" + + displaywithnewline : kittify : bytevector->u8-list : string->utf8 "Karlsruhe Institut für Technologie (KIT)" + + displaywithnewline : utf8->string : u8-list->bytevector : unkittify " + 1F. 1c.1 u.1o .1v. 1u.1x.1j + .1g .Y. 1D.1 q.1v .1w.1k.1 + w.1x .1 w.Y.1h. 3F.3 8.1u + .Y.1 Q. 1g.1e.1 j.1q .1r. + 1o.1 r.1i . 1k.1 g.Y. f.1F + .1D.1Q.g...... .... .... .... + Karlsruher Institut fuer Technologie + " + + displaywithnewline " + + === KIT, IMK, RemoteC ===" + + displaywithnewline : kittify : map shiftbytedownfortext : bytevector->u8-list : string->utf8 "Karlsruhe Institut für Technologie (KIT), IMK-ASF, RemoteC" + + displaywithnewline " + + === kittifyscript ===" + + displaywithnewline : kittytextfile "examples/kit-encode.w" + + + ; TODO: Final step: Add commandline handling which allows to write into files and set the text flag and so on. ; ./kit-encode [-e|--encode|-d|--decode] [--text] [--template file] [--killstring "stringtoremove" (mutliple times)] [-o|--output file] [file|-] diff --git a/examples/map-product-sums.w b/examples/map-product-sums.w new file mode 100644 --- /dev/null +++ b/examples/map-product-sums.w @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples map-product-sums) main)' -s "$0" "$@" +; !# + +use-modules : (srfi srfi-42) + +define-module : examples map-product-sums + +define : list-product-sums list-of-numbers + . "return a list with the sum of the products of each number with all other numbers. + + >>> map-product-sums '(2 4 6) + (list (+ (* 2 4) (* 2 6)) (+ (* 4 2) (* 4 6)) (+ (* 6 2) (* 6 4))) + " + map (lambda (x) (apply + x)) + list-ec (: i list-of-numbers) + map (lambda (x) (* i x)) + cons (- i) list-of-numbers + + +define : main . args + write : list-product-sums '(2 4 6) + diff --git a/examples/multithreaded-magic.w b/examples/multithreaded-magic.w --- a/examples/multithreaded-magic.w +++ b/examples/multithreaded-magic.w @@ -1,6 +1,9 @@ -#!./wisp-multiline.sh +#!/usr/bin/env sh +exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples multithreaded-magic) main)' -s "$0" "$@" ; !# +define-module : examples multithreaded-magic + ; Mathematical magic: Always get one. ; ; Via http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseQuestionsnode18.html @@ -8,6 +11,8 @@ ; ; this is the wisp scheme version which I want to compare with the fortran version. +; Call as PATH=~/guile/meta:$PATH ./examples/multithreaded-magic.w + use-modules ice-9 format ice-9 futures @@ -15,12 +20,17 @@ use-modules define : magic-threaded mutex futures integer ; this can cause unordered output. It’s fun anyway : - set! futures : append futures : list : future : with-mutex mutex : format #t "~30r\n" integer - if : not : = integer 1 - if : even? integer - magic-threaded mutex futures : / integer 2 - magic-threaded mutex futures : truncate : + 1 : / integer 3 - for-each touch futures + let + : + futures + cons : future : with-mutex mutex : format #t "~30r\n" integer + . futures + if : not : = integer 1 + if : even? integer + magic-threaded mutex futures {integer / 2} + magic-threaded mutex futures + truncate : + 1 {integer / 3} + for-each touch futures define : magic integer magic-threaded @@ -35,7 +45,8 @@ define : magic-simple integer magic-simple : / integer 2 magic-simple : truncate : + 1 : / integer 3 -display ";;; multithreaded magic ;;;\n" -magic 456189456156456196152615 -display ";;; simple magic ;;;\n" -magic-simple 456189456156456196152615 +define : main args + display ";;; multithreaded magic ;;;\n" + magic 456189456156456196152615 + display ";;; simple magic ;;;\n" + magic-simple 456189456156456196152615 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/examples/property.w b/examples/property.w new file mode 100755 --- /dev/null +++ b/examples/property.w @@ -0,0 +1,29 @@ +#!/usr/bin/env sh +# -*- wisp -*- +exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples property) main)' -s "$0" "$@" +; !# + +define-module : examples property + . #:export : main + +; FIXME: this does not work when called from guile, but it works when +; first translating it to scheme and then calling the scheme file. + +; The following works: + +; guile ../wisp.scm property.w > property.scm; guile -e '(@@ (examples property) main)' -s property.scm + +define y 5 +define-syntax z + identifier-syntax : var y + : set! var val + set! y : + 1 val + +define : main args + write args + newline + write z + newline + set! z 5 + write z + newline diff --git a/guildhall-packages/newbase60/newbase60.scm b/guildhall-packages/newbase60/newbase60.scm new file mode 100644 --- /dev/null +++ b/guildhall-packages/newbase60/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/newbase60/pkg-list.scm b/guildhall-packages/newbase60/pkg-list.scm new file mode 100644 --- /dev/null +++ b/guildhall-packages/newbase60/pkg-list.scm @@ -0,0 +1,6 @@ +(package (newbase60 (0)) + (synopsis "Implementation of Tanteks New Base 60") + (libraries + (scm -> "newbase60")) + (programs + ("newbase60.scm"))) 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/tests/quotecolon.scm b/tests/quotecolon.scm --- a/tests/quotecolon.scm +++ b/tests/quotecolon.scm @@ -9,4 +9,4 @@ (a b) (c)) - +(define a (quasiquote ,(+ 2 2))) diff --git a/tests/quotecolon.w b/tests/quotecolon.w --- a/tests/quotecolon.w +++ b/tests/quotecolon.w @@ -8,3 +8,5 @@ define a ' : 1 2 3 define a b c + +define a : quasiquote , : + 2 2 diff --git a/wisp-guile.w b/wisp-guile.w --- a/wisp-guile.w +++ b/wisp-guile.w @@ -19,6 +19,29 @@ ;; ;; -Author: Arne Babenhauserheide +;; Copyright (C) Arne Babenhauserheide (2013--2015). All Rights Reserved. + +;; 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. + + define-module : wisp . #:export : wisp2lisp wisp-chunkreader diff --git a/wisp-mode.el b/wisp-mode.el --- a/wisp-mode.el +++ b/wisp-mode.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2013 Arne Babenhauserheide <arne_bab@web.de> ;; Author: Arne Babenhauserheide <arne_bab@web.de> -;; Version: 0.2 +;; Version: 0.2.1 ;; Keywords: languages, lisp ;; This program is free software; you can redistribute it and/or @@ -37,6 +37,7 @@ ;; ;; ChangeLog: ;; +;; - 0.2.1: Disable electric-indent-local-mode in wisp-mode buffers. ;; - 0.2: Fixed the regular expressions. Now org-mode HTML export works with wisp-code. ;; ;;; Code: @@ -49,6 +50,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-reader.w b/wisp-reader.w --- a/wisp-reader.w +++ b/wisp-reader.w @@ -14,6 +14,8 @@ define-module : language wisp spec . #:use-module : wisp-scheme . #:use-module : system base compile . #:use-module : system base language + . #:use-module : language scheme compile-tree-il + . #:use-module : language scheme decompile-tree-il . #:export : wisp ; Set locale to something which supports unicode. Required to avoid using fluids. @@ -23,59 +25,26 @@ setlocale LC_ALL "" ;;; Language definition ;;; -define : compile-scheme x e opts - values x e e - -define : decompile-scheme x e opts - values x e - -define wisp-pending-port : make-object-property - -; Code thanks to Mark Weaver -; define : read-one-wisp-sexp port env -; define : read-wisp-chunk -; if : eof-object? : peek-char port -; read-char port ; return eof: we’re done -; let : : s : wisp2lisp : wisp-chunkreader port -; set! : wisp-pending-port port -; open-input-string s -; try-pending -; define : try-pending -; let : : pending-port : wisp-pending-port port -; if pending-port -; let : : x : read pending-port -; if : eof-object? x -; read-wisp-chunk -; . x -; read-wisp-chunk -; try-pending - - define wisp-pending-sexps : list define : read-one-wisp-sexp port env - define : wisp-scheme-read-chunk-env - cond - : eof-object? : peek-char port - read-char port ; return eof: we’re done - else - set! wisp-pending-sexps - append wisp-pending-sexps : wisp-scheme-read-chunk port - try-pending - define : try-pending - if : null? wisp-pending-sexps - wisp-scheme-read-chunk-env - let : : sexp : car wisp-pending-sexps - set! wisp-pending-sexps : cdr wisp-pending-sexps - . sexp - try-pending + cond + : eof-object? : peek-char port + read-char port ; return eof: we’re done + else + let : : chunk : wisp-scheme-read-chunk port + cond + : not : null? chunk + car chunk + else + . #f define-language wisp - . #:title "Wisp Scheme Syntax THIS IS EXPERIMENTAL, USE AT YOUR OWN RISK" + . #:title "Wisp Scheme Syntax. See SRFI-119 for details. THIS IS EXPERIMENTAL, USE AT YOUR OWN RISK" ; . #:reader read-one-wisp-sexp . #:reader : lambda (port env) : let ((x (read-one-wisp-sexp port env))) x - . #:compilers `((scheme . ,compile-scheme)) - . #:decompilers `((scheme . ,decompile-scheme)) + . #:compilers `((tree-il . ,compile-tree-il)) + . #:decompilers `((tree-il . ,decompile-tree-il)) . #:evaluator : lambda (x module) : primitive-eval x . #:printer write ; TODO: backtransform to wisp? Use source-properties? . #:make-default-environment diff --git a/wisp-scheme.w b/wisp-scheme.w --- a/wisp-scheme.w +++ b/wisp-scheme.w @@ -1,4 +1,5 @@ #!/bin/bash +# -*- wisp -*- exec guile -L . --language=wisp -s "$0" "$@" ; !# @@ -16,6 +17,28 @@ exec guile -L . --language=wisp -s "$0" ;; then simply reuse the appropriate function from the generic wisp ;; preprocessor. +;; Copyright (C) Arne Babenhauserheide (2014--2015). All Rights Reserved. + +;; 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. + define-module : wisp-scheme . #:export (wisp-scheme-read-chunk wisp-scheme-read-all @@ -43,7 +66,11 @@ define : line-real-indent line . indent define : line-code line - cdr line + 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 @@ -110,6 +137,16 @@ define : wisp-read port 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. + ; TODO: Somehow store source-properties. The commented-out code below does not work. + ; catch #t + ; lambda () + ; write : source-properties symbol-or-symbols + ; set-source-property! symbol-or-symbols 'filename : port-filename port + ; set-source-property! symbol-or-symbols 'line : 1+ : port-line port + ; set-source-property! symbol-or-symbols 'column : port-column port + ; write : source-properties symbol-or-symbols + ; lambda : key . arguments + ; . #f . repr-symbol let unpeek : remaining peeked @@ -195,16 +232,20 @@ define : wisp-scheme-read-chunk-lines po currentindent 0 currentsymbols '() emptylines 0 - 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). + 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 : and inindent : equal? #\space next-char read-char port ; remove char loop @@ -258,6 +299,10 @@ define : wisp-scheme-read-chunk-lines po 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. @@ -326,6 +371,12 @@ define : line-code-replace-inline-colons : 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. @@ -353,12 +404,53 @@ define : line-strip-lone-colon line . line define : line-finalize line - . "Process all wisp-specific information in a line and strip it" - line-code-replace-inline-colons - line-strip-indentation-marker - line-strip-lone-colon - line-strip-continuation 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 +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 + +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 define : wisp-scheme-indentation-to-parens lines . "Add parentheses to lines and remove the indentation markers" @@ -447,7 +539,7 @@ define : wisp-scheme-indentation-to-pare append processed if : line-continues? current-line . line - list line + wisp-add-source-properties-from line : list line cdr unprocessed ; recursion here . indentation-levels : < current-line-indentation next-line-indentation @@ -537,8 +629,16 @@ define : wisp-replace-paren-quotation-re list : list 'quote : map wisp-replace-paren-quotation-repr b : '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 ... @@ -613,7 +713,6 @@ Match is awesome!" a . a - define : wisp-scheme-read-chunk port . "Read and parse one chunk of wisp-code" let : : lines : wisp-scheme-read-chunk-lines port @@ -621,7 +720,8 @@ define : wisp-scheme-read-chunk port wisp-replace-empty-eof wisp-unescape-underscore-and-colon wisp-replace-paren-quotation-repr - wisp-scheme-indentation-to-parens lines + wisp-propagate-source-properties + wisp-scheme-indentation-to-parens lines define : wisp-scheme-read-all port . "Read all chunks from the given port"