(Arne Babenhauserheide)
2014-07-14: merge merge
diff --git a/docs/srfi.org b/docs/srfi.org --- a/docs/srfi.org +++ b/docs/srfi.org @@ -78,11 +78,15 @@ Remember, even if a proposal becomes an - Arne Babenhauserheide +** Acknowledgments + +Thanks for lots of constructive discussions goes to Alan Manuel K. Gloria and David A. Wheeler. + * Related SRFIs - SRFI-49 (Indentation-sensitive syntax): superceded by this SRFI, -- SRFI-110 (Sweet-expressions (t-expressions)): superceded by this SRFI, -- SRFI-105 (neoteric expressions and curly infix): supported by treating curly braces like brackets and parens, and +- SRFI-110 (Sweet-expressions (t-expressions)): alternative to this SRFI, +- SRFI-105 (neoteric expressions and curly infix): supported in this SRFI by treating curly braces like brackets and parens. - SRFI-30 (Nested Multi-line comments): complex interaction. Should be avoided at the beginning of lines, because it can make the indentation hard to distinguish for humans. SRFI-110 includes them, so there might be value in adding them. The wisp reference implementation does not treat them specially, though, which might create arbitrary complications. * Rationale @@ -102,7 +106,7 @@ As noted in SRFI-110, there are a number 1 #+END_SRC -SRFI-110 improves a lot over the implementation of SRFI-49 and resolves the group-naming by introducing 3 different grouping-syntaxes (=$=, =\\= and =<* *>=). These additional syntax-elements however hurt readability for newcomers a lot. They make some code written in SRFI-110 look quite similar to perl and bash: +SRFI-110 improves a lot over the implementation of SRFI-49. It resolves the group-naming and tries to reduce the need to continue the argument-list by introducing 3 different grouping-syntaxes (=$=, =\\= and =<* *>=). These additional syntax-elements however hurt readability for newcomers a lot (obviously the authors of SRFI-110 disagree with this assertion. Their point is discussed in SRFI-110 in the section about wisp). The additional syntax elements lead to structures like the following: #+BEGIN_SRC scheme myfunction x: \\ original-x @@ -122,12 +126,18 @@ This is not only hard to read, but also Like SRFI-49 SRFI-110 also cannot continue the argument-list without resorting to single-element lines, though it reduces this problem by advertising the use of neoteric expressions (SRFI-105). +** Advantages of Wisp + Wisp draws on the strength of SRFI-110 but avoids its complexities. It was actually conceived and improved in the discussions within the readable-project which preceded SRFI-110 and there is a comparison between readable in wisp in SRFI-110. -Like SRFI-110, wisp is general and homoiconic and interacts nicely with SRFI-105 (neoteric expressions and curly infix). Like SRFI-110, the expressions are the same in the REPL and in code-files. +Like SRFI-110, wisp is general and homoiconic and interacts nicely with SRFI-105 (neoteric expressions and curly infix). Like SRFI-110, the expressions are the same in the REPL and in code-files. Like SRFI-110, wisp has been used for implementing multiple smaller programs, though the biggest program in wisp is still its implementation. But unlike SRFI-110, wisp only uses the minimum of additional syntax-elements which are necessary to support arbitrary code-structures with indentation-sensitive code which is intended to be shared over the internet. To realize these syntax-elements, it generalizes existing syntax and draws on the most common non-letter non-math characters in prose. This allows keeping the actual representation of the code elegant and inviting to newcomers. +** Disadvantages of Wisp + +Using the colon as syntax element keeps the code very close to written prose, but it can interfere with type definitions as for example used in Typed Racket[fn:6]. This can be mitigated in let- and lambda-forms by using the parenthesized form. When doing so, wisp avoid the double-paren for type-declarations and as such makes them easier to catch by eye. For function definitions (the only =define= call where type declarations are needed in typed-racket[fn:7]), a =declare= macro directly before the =define= should work well. + * Specification The specification is separated into four parts: A general overview of the syntax, a more detailed description, justifications for each added syntax element and clarifications for technical details. @@ -138,7 +148,7 @@ The basic rules for wisp-code can be def *** Wisp syntax 1/4: function calls -**** Indentation +Indentation: #+BEGIN_SRC wisp display @@ -156,7 +166,7 @@ becomes *** Wisp syntax 2/4: Continue Argument list -**** The period +The period: #+BEGIN_SRC wisp + 5 @@ -176,7 +186,7 @@ This also works with just one argument a *** Wisp syntax 3/4: Double Parens -**** The colon[fn:3] +The colon:[fn:3] #+BEGIN_SRC wisp let @@ -198,7 +208,7 @@ becomes *** Wisp syntax 4/4: Resilient Indentation -**** The underscore (optional) +The underscore (optional): #+BEGIN_SRC wisp let @@ -221,36 +231,32 @@ becomes *** Summary -#+html: <small> -http://draketo.de/light/english/wisp-lisp-indentation-preprocessor#sec-4 -#+html: </small> - -The syntax shown here is the minimal synatx required for the goal of wisp: indentation-based, general lisp with a simple preprocessor, and code which can be shared easily on the internet: +The syntax shown here is the minimal syntax required for the goal of wisp: indentation-based, general lisp with a simple preprocessor, and code which can be shared easily on the internet: - =.= to continue the argument list - =:= for double parens - =_= to survive HTML ** More detailed: Wisp syntax rules + +*** Unindented line -*** *A line without indentation is a function call*, just as if it would start with a bracket. +*A line without indentation is a function call*, just as if it would start with a bracket. #+BEGIN_SRC wisp display "Hello World!" ; (display "Hello World!") #+END_SRC - - -*** *A line which is more indented than the previous line is a sibling to that line*: It opens a new bracket. +*** Sibling line +*A line which is more indented than the previous line is a sibling to that line*: It opens a new bracket. #+BEGIN_SRC wisp display ; (display string-append "Hello " "World!" ; (string-append "Hello " "World!")) #+END_SRC - - -*** *A line which is not more indented than previous line(s) closes the brackets of all previous lines which have higher or equal indentation*. You should only reduce the indentation to indentation levels which were already used by parent lines, else the behaviour is undefined. +*** Closing line +*A line which is not more indented than previous line(s) closes the brackets of all previous lines which have higher or equal indentation*. You should only reduce the indentation to indentation levels which were already used by parent lines, else the behaviour is undefined. #+BEGIN_SRC wisp display ; (display @@ -258,17 +264,17 @@ The syntax shown here is the minimal syn display "Hello Again!" ; (display "Hello Again!") #+END_SRC +*** Prefixed line - -*** *To add any of ' , ` #' #, #` or #@, to the first bracket on a line, just prefix the line with that symbol* followed by at least one space. Implementations are free to add more prefix symbols. +*To add any of ' , ` #' #, #` or #@, to the first bracket on a line, just prefix the line with that symbol* followed by at least one space. Implementations are free to add more prefix symbols. #+BEGIN_SRC wisp ' "Hello World!" ; '("Hello World!") #+END_SRC - -*** *A line whose first non-whitespace characters are a dot followed by a space (". ") does not open a new bracket: it is treated as simple continuation of the first less indented previous line*. In the first line this means that this line does not start with a bracket and does not end with a bracket, just as if you had directly written it in lisp without the leading ". ". +*** Continuing line +*A line whose first non-whitespace characters is a dot followed by a space (". ") does not open a new bracket: it is treated as simple continuation of the first less indented previous line*. In the first line this means that this line does not start with a bracket and does not end with a bracket, just as if you had directly written it in lisp without the leading ". ". #+BEGIN_SRC wisp string-append "Hello" ; (string-append "Hello" @@ -277,8 +283,8 @@ The syntax shown here is the minimal syn #+END_SRC - -*** *A line which contains only whitespace and a colon (":") defines an indentation level at the indentation of the colon*. It opens a bracket which gets closed by the next less-indented line. If you need to use a colon by itself. you can escape it as "\:". +*** Empty indentation level +*A line which contains only whitespace and a colon (":") defines an indentation level at the indentation of the colon*. It opens a bracket which gets closed by the next less-indented line. If you need to use a colon by itself. you can escape it as "\:". #+BEGIN_SRC wisp let ; (let @@ -288,8 +294,8 @@ The syntax shown here is the minimal syn #+END_SRC - -*** *A colon sourrounded by whitespace (" : ") starts a bracket which gets closed at the end of the line*. +*** Inline Colon +*A colon sourrounded by whitespace (" : ") starts a bracket which gets closed at the end of the line*. #+BEGIN_SRC wisp define : hello who ; (define (hello who) @@ -297,8 +303,10 @@ The syntax shown here is the minimal syn string-append "Hello " who "!" ; (string-append "Hello " who "!"))) #+END_SRC +If the colon starts a line, it starts a bracket which gets closed at the end of the line *and* defines an indentation level at the position of the colon. -*** *You can replace any number of consecutive initial spaces by underscores*, as long as at least one whitespace is left between the underscores and any following character. You can escape initial underscores by prefixing the first one with \ ("\___ a" → "(___ a)"), if you have to use them as function names. +*** Initial Underscores +*You can replace any number of consecutive initial spaces by underscores*, as long as at least one whitespace is left between the underscores and any following character. You can escape initial underscores by prefixing the first one with \ ("\___ a" → "(___ a)"), if you have to use them as function names. #+BEGIN_SRC wisp define : hello who ; (define (hello who) @@ -306,18 +314,44 @@ The syntax shown here is the minimal syn ___ string-append "Hello " who "!" ; (string-append "Hello " who "!"))) #+END_SRC +*** Parens and Strings +*Linebreaks inside parentheses and strings are not considered linebreaks* for parsing indentation. To use parentheses at the beginning of a line without getting double parens, prefix the line with a period. + +#+BEGIN_SRC wisp +define : stringy s + string-append s "can be varied as follows: +" + string-capitalize s + string-reverse s + . (string-capitalize + (string-reverse s)) + . " +" + +#+END_SRC ** Clarifications - Code-blocks end after 2 empty lines followed by a newline. Indented non-empty lines after 2 empty lines should be treated as error. A line is empty if it only contains whitespace. -- square brackets and curly braces should be treated the same way as parentheses: They stop the indentation processing until they are closed. +- Inside parentheses wisp parsing is disabled. Consequently linebreaks inside parentheses are not considered linebreaks for wisp-parsing. For the parser everything which happens inside parentheses is considered as a black box. -** Syntax justification +- Square brackets and curly braces should be treated the same way as parentheses: They stop the indentation processing until they are closed. + +- Likewise linebreaks inside strings are not considered linebreaks for wisp-parsing. + +- A colon (:) at the beginning of a line adds an extra open parentheses that gets closed at end-of-line (rule 4.2.7) *and* defines an indentation level. + +* Syntax justification /I do not like adding any unnecessary syntax element to lisp. So I want to show explicitely why the syntax elements are required./ -*** . (the dot) +#+html: <small> +See also http://draketo.de/light/english/wisp-lisp-indentation-preprocessor#sec-4 +#+html: </small> + + +** . (the dot) The dot at the beginning of the line as marker of the continuation of a variable list is a generalization of using the dot as identity function - which is an implementation detail in many lisps. @@ -327,7 +361,7 @@ So for the single variable case, this wo Essentially this dot-rule means that we mark variables in the code instead of function calls, since in Lisp variables at the beginning of a line are much rarer than in other programming languages. In lisp assigning a value to a variable is a function call while it is a syntax element in many other languages, so what would be a variable at the beginning of a line in other languages is a function call in lisp.. -*** : (the colon) +** : (the colon) For double brackets and for some other cases we must have a way to mark indentation levels without any code. I chose the colon, because it is the most common non-alpha-numeric character in normal prose which is not already reserved as syntax by lisp when it is surrounded by whitespace, and because it already gets used for marking keyword arguments to functions in Emacs Lisp, so it does not add completely alien characters. @@ -363,7 +397,7 @@ doublelet The need to be able to represent things like this is the real reason, why the colon exists. The inline and start-of-line use is only a generalization of that principle (we add a syntax-element, so we should see how far we can push it to reduce the effective cost of introducing the additional syntax). -**** Clever whytespace-parsing which would not work +*** Clever whitespace-parsing which would not work There are two alternative ways to tackle this issue: deferred level-definition and fixed-width indentation. @@ -393,7 +427,7 @@ if fixstuff #+END_SRC -*** _ (the underscore) +** _ (the underscore) In Python the whitespace hostile html already presents problems with sharing code - for example in email list archives and forums. But in Python the indentation can mostly be inferred by looking at the previous line: If that ends with a colon, the next line must be more indented (there is nothing to clearly mark reduced indentation, though). In wisp we do not have that help, so we need a way to survive in that hostile environment. @@ -403,17 +437,17 @@ You can still use underscores anywhere b * Implementation -This reference implementation realizes a general wisp-preprocessor which can be used for any lisp-like language. It contains special syntax-constructs for scheme, though. The reference-preprocessor uses GNU Guile and can also be used at the REPL. +This reference implementation realizes a general wisp-preprocessor which can be used for any lisp-like language. It contains special syntax-constructs for scheme, though. The reference-preprocessor uses GNU Guile and can also be used at the REPL. Due to being a simple preprocessor, wisp can also be implemented as an external program which gets called on reading. It does not actually have to understand the code itself. -A wisp-preprocessor which is specialiized for scheme should be much easier to realize by using the parsing methods from an existing scheme implementation. +A wisp-preprocessor which is specialiized for scheme should be much easier to realize, though, by using the parsing methods from an existing scheme implementation. -Since reference implementation is very heavyweight, it would be great to have someone step up and create a more lightweight scheme-specific alternative. To allow for this, the test-suite in the next chapter only contains scheme-specific snippets. +Since generality of the reference implementation makes it quite heavyweight, it would be great to have someone step up and create a more lightweight scheme-specific alternative. To allow for this, the test-suite in the next chapter only contains scheme-specific snippets. ** The generic wisp preprocessor (code) TODO: Include the code from http://draketo.de/proj/wisp -* Test Suite +** Test Suite The wisp test-suite consists of a large number of wisp-snippets and the corresponding scheme-code. A wisp-implementation may call itself compliant to the wisp test-suite if it successfully converts each wisp-snippet into the corresponging scheme-snippet. Blank lines at the end of the file and non-functional white-space in the produced scheme-file do not matter for this purpose. @@ -423,7 +457,7 @@ The test-suite included here only contai /TODO: Some of the snippets were transformed from emacs lisp to scheme by hand and this might have introduced bugs. They still need to be tested again./ -** tests/syntax-underscore.w +*** tests/syntax-underscore.w #+begin_src wisp define : a b c _ d e @@ -436,7 +470,7 @@ define : _ \_ #+end_src -** tests/syntax-underscore.scm +*** tests/syntax-underscore.scm #+begin_src scheme (define (a b c) (d e @@ -451,7 +485,7 @@ define : _ #+end_src -** tests/syntax-strings-parens.w +*** tests/syntax-strings-parens.w #+begin_src wisp ; Test linebreaks in strings and brackets @@ -477,7 +511,7 @@ li lo (mabba) } #+end_src -** tests/syntax-strings-parens.scm +*** tests/syntax-strings-parens.scm #+begin_src scheme ; Test linebreaks in strings and brackets @@ -503,7 +537,7 @@ li lo (mabba) }) #+end_src -** tests/syntax-indent.w +*** tests/syntax-indent.w #+begin_src wisp define hello who @@ -520,7 +554,7 @@ define . b c #+end_src -** tests/syntax-indent.scm +*** tests/syntax-indent.scm #+begin_src scheme (define (hello who) @@ -539,13 +573,13 @@ define #+end_src -** tests/syntax-empty.w +*** tests/syntax-empty.w #+begin_src wisp #+end_src -** tests/syntax-empty.scm +*** tests/syntax-empty.scm #+begin_src scheme #+end_src -** tests/syntax-dot.w +*** tests/syntax-dot.w #+begin_src wisp define : foo . "bar" @@ -559,7 +593,7 @@ newline display : bar newline #+end_src -** tests/syntax-dot.scm +*** tests/syntax-dot.scm #+begin_src scheme (define (foo) "bar") @@ -575,7 +609,7 @@ newline #+end_src -** tests/syntax-colon.w +*** tests/syntax-colon.w #+begin_src wisp let : @@ -614,7 +648,7 @@ define : \: \: #+end_src -** tests/syntax-colon.scm +*** tests/syntax-colon.scm #+begin_src scheme (let ( @@ -655,7 +689,7 @@ define : \: #+end_src -** tests/sublist.w +*** tests/sublist.w #+begin_src wisp ; sublists allow to start single line function calls with a colon ( : ). ; @@ -663,7 +697,7 @@ define : a b c let : : e . f . g #+end_src -** tests/sublist.scm +*** tests/sublist.scm #+begin_src scheme ; sublists allow to start single line function calls with a colon ( : ). @@ -673,19 +707,19 @@ define : a b c #+end_src -** tests/shebang.w +*** tests/shebang.w #+begin_src wisp #!/usr/bin/wisp.py # !# ; This tests shebang lines #+end_src -** tests/shebang.scm +*** tests/shebang.scm #+begin_src scheme #!/usr/bin/wisp.py # !# ; This tests shebang lines #+end_src -** tests/readable-tests.w +*** tests/readable-tests.w #+begin_src wisp define : fibfast n if : < n 2 @@ -726,7 +760,7 @@ define : add-if-all-numbers lst + : car lst loop : cdr lst #+end_src -** tests/readable-tests.scm +*** tests/readable-tests.scm #+begin_src scheme (define (fibfast n) (if (< n 2)) @@ -768,7 +802,7 @@ define : add-if-all-numbers lst (loop (cdr lst))))))))) #+end_src -** tests/range.w +*** tests/range.w #+begin_src wisp import : rnrs @@ -795,7 +829,7 @@ define range display : apply string-append "" : map number->string : range 5 newline #+end_src -** tests/range.scm +*** tests/range.scm #+begin_src scheme (import (rnrs)) @@ -823,7 +857,7 @@ newline (newline) #+end_src -** tests/quotecolon.w +*** tests/quotecolon.w #+begin_src wisp #!/home/arne/wisp/wisp-multiline.sh ; !# @@ -836,7 +870,7 @@ define a b c #+end_src -** tests/quotecolon.scm +*** tests/quotecolon.scm #+begin_src scheme #!/home/arne/wisp/wisp-multiline.sh ; !# @@ -851,7 +885,7 @@ define #+end_src -** tests/namedlet.w +*** tests/namedlet.w #+begin_src wisp #!/home/arne/wisp/wisp-multiline.sh ; !# @@ -864,7 +898,7 @@ let hello display who hello : + 1 who #+end_src -** tests/namedlet.scm +*** tests/namedlet.scm #+begin_src scheme #!/home/arne/wisp/wisp-multiline.sh ; !# @@ -879,13 +913,13 @@ let hello #+end_src -** tests/mtest.w +*** tests/mtest.w #+begin_src wisp #!/home/arne/wisp/wisp-multiline.sh !# display 1 #+end_src -** tests/mtest.scm +*** tests/mtest.scm #+begin_src scheme #!/home/arne/wisp/wisp-multiline.sh !# @@ -893,7 +927,7 @@ display 1 #+end_src -** tests/flexible-parameter-list.w +*** tests/flexible-parameter-list.w #+begin_src wisp ; Test using a . as first parameter on a line by prefixing it with a second . define @@ -908,7 +942,7 @@ define a 0 "123" "345" "567" #+end_src -** tests/flexible-parameter-list.scm +*** tests/flexible-parameter-list.scm #+begin_src scheme ; Test using a . as first parameter on a line by prefixing it with a second . (define @@ -925,7 +959,7 @@ a 0 "123" "345" "567" #+end_src -** tests/factorial.w +*** tests/factorial.w #+begin_src wisp ;; short version ; note: once you use one inline colon, all the following forms on that @@ -950,7 +984,7 @@ define : factorial n display : factorial 5 #+end_src -** tests/factorial.scm +*** tests/factorial.scm #+begin_src scheme ;; short version ; note: once you use one inline colon, all the following forms on that @@ -977,7 +1011,7 @@ display : factorial 5 #+end_src -** tests/example.w +*** tests/example.w #+begin_src wisp define (a b c) let @@ -1039,7 +1073,7 @@ let : : a b . a #+end_src -** tests/example.scm +*** tests/example.scm #+begin_src scheme (define (a b c) (let @@ -1103,7 +1137,7 @@ a #+end_src -** tests/continuation.w +*** tests/continuation.w #+begin_src wisp a b c d e . f g h @@ -1114,7 +1148,7 @@ concat "I want " . " - " username #+end_src -** tests/continuation.scm +*** tests/continuation.scm #+begin_src scheme (a b c d e f g h @@ -1127,12 +1161,12 @@ concat "I want " #+end_src -** tests/btest.w +*** tests/btest.w #+begin_src wisp display "b" newline #+end_src -** tests/btest.scm +*** tests/btest.scm #+begin_src scheme (display "b") (newline) @@ -1159,4 +1193,7 @@ newline [fn:4] I used a double let without action as example for the colon-syntax, even though that does nothing, because that makes it impossible to use later indentation to mark an intermediate indentation-level. Another reason why I would not use later indentation to define whether something earlier is a single or double indent is that this would call for subtle and really hard to find errors: [fn:5] To run the tests in the wisp testsuite with a separately built GNU Guile, you can use any given guile interpreter by adjusting the following command: =PATH=~/guile-2.0.11/meta:${PATH} ./runtests.sh= - + +[fn:6] Typed Racket uses calls of the form =(: x Number)= to declare types. These forms can still be used in parenthesized form, but not in wisp-form (as the colon has to be replaced with =\:=). + +[fn:7] In most cases type-declarations are not needed in typed racket, since the type can be inferred. See [[http://docs.racket-lang.org/ts-guide/more.html?q=typed#%28part._when-annotations~3f%29][When do you need type annotations?]] diff --git a/docs/why-wisp.org b/docs/why-wisp.org --- a/docs/why-wisp.org +++ b/docs/why-wisp.org @@ -155,7 +155,7 @@ myfunction /This breaks elegance 1/ -/Also the problems of SRFI-49 are preserved/ +/The problems of SRFI-49 are preserved, but their impact reduced./ * Summary: Why wisp? @@ -184,7 +184,7 @@ becomes (newline) #+END_SRC -* Wisp syntax 2/4: Continue Argument list +* Wisp syntax 2/4: Continue Arguments ** The dot diff --git a/examples/d20world.w b/examples/d20world.w --- a/examples/d20world.w +++ b/examples/d20world.w @@ -66,8 +66,8 @@ let loop : : relationships neighbors-hel else let* : cur : car relationships - idx : 1- : car cur - vec : cdr cur + idx : 1- : car cur + vec : cdr cur vector-set! world idx : 1+ idx vector-set! neighbors idx : make-vector 3 let setidx : : idxtoset '(0 1 2) @@ -142,31 +142,25 @@ define : d20-cursor-up-text world-vector format #t "[~AA" : 1- : length lines define : d20-diffuse world neighbors D - . "Diffuse the values on the d20 using the diffusion constant D. Step 1: Simply iterative." - let loop : : neighbors-to-diffuse : iota : vector-length neighbors - cond - : null? neighbors-to-diffuse - . world - else - let : : edges-to-diffuse-targets : vector-ref neighbors (car neighbors-to-diffuse) - let* - : edges-to-diffuse : append (list (car neighbors-to-diffuse)) : vector->list edges-to-diffuse-targets - idx0 : list-ref edges-to-diffuse 0 - idx1 : list-ref edges-to-diffuse 1 - idx2 : list-ref edges-to-diffuse 2 - idx3 : list-ref edges-to-diffuse 3 - val0 : vector-ref world idx0 - val1 : vector-ref world idx1 - val2 : vector-ref world idx2 - val3 : vector-ref world idx3 - diff0 : * (/ D 3) : - val1 val0 - diff1 : * (/ D 3) : - val2 val0 - diff2 : * (/ D 3) : - val3 val0 - vector-set! world idx0 : + val0 diff0 diff1 diff2 - vector-set! world idx1 : - val1 diff0 - vector-set! world idx2 : - val2 diff1 - vector-set! world idx3 : - val3 diff2 - loop : cdr neighbors-to-diffuse + . "Diffuse the values on the d20 using the diffusion constant D. Step 1: Simply iterative." + let leapfrog : : targets '(0 1 2) + if : null? targets + . world + let loop : : neighbors-to-diffuse : iota : vector-length neighbors + cond + : null? neighbors-to-diffuse + leapfrog : cdr targets + else + let* + : originidx : car neighbors-to-diffuse ; index in world and in neighbors + targetleap : car targets + targetidx : vector-ref (vector-ref neighbors originidx) targetleap + originval : vector-ref world originidx + targetval : vector-ref world targetidx + diff : * (/ D 3) : - targetval originval + vector-set! world originidx : + originval diff + vector-set! world targetidx : - targetval diff + loop : cdr neighbors-to-diffuse define : d20-advect world advection-directions A @@ -208,6 +202,28 @@ format #t "Diffuse ~A\n" 0.1 d20-diffuse world neighbors 0.1 display : d20-as-text world newline +format #t "Diffuse: ~A*(~A)\n" 100 0.1 +let loop : : steps 100 + cond + : = 0 steps + . world + else + d20-diffuse world neighbors 0.1 + loop : 1- steps +display : d20-as-text world +newline +let + : number 20 + val 1 + format #t "disturb: ~A to ~A\n" number val + vector-set! world (1- number) val + display : d20-as-text world + newline +format #t "Diffuse ~A\n" 0.1 +d20-diffuse world neighbors 0.1 +display : d20-as-text world +newline + format #t "Advect: ~A*(~A)\n" 1000 0.001 let loop : : steps 1000 cond diff --git a/tests/linebreaks.scm b/tests/linebreaks.scm new file mode 100644 --- /dev/null +++ b/tests/linebreaks.scm @@ -0,0 +1,16 @@ +; Test linebreaks in strings and brackets + +("flubbub + +flabbab") + +(hrug (nadda +madda gadda "shoktom + mee" " sep +ka" + hadda) + (gom)) + +(flu) + + diff --git a/tests/websafe-indent.scm b/tests/websafe-indent.scm new file mode 100644 --- /dev/null +++ b/tests/websafe-indent.scm @@ -0,0 +1,7 @@ +(defun a (b c) + (d e + (f) + (g h) + i)) + +