Compare commits

..

2 commits

55 changed files with 2557 additions and 3384 deletions

4
.gitignore vendored
View file

@ -21,7 +21,3 @@ Sysout*.lsp
*.pdf *.pdf
src/beowulf/scratch.clj src/beowulf/scratch.clj
.portal/vs-code.edn
.portal/

164
README.md
View file

@ -38,7 +38,7 @@ LISP 1.5 is to all Lisp dialects as Beowulf is to English literature.
A work-in-progress towards an implementation of Lisp 1.5 in Clojure. The A work-in-progress towards an implementation of Lisp 1.5 in Clojure. The
objective is to build a complete and accurate implementation of Lisp 1.5 objective is to build a complete and accurate implementation of Lisp 1.5
as described in the manual, with, in so far as is possible, exactly the as described in the manual, with, in so far as is possible, exactly the
same bahaviour - except as documented below. same behaviour — except as documented below.
### BUT WHY?!!?! ### BUT WHY?!!?!
@ -62,14 +62,11 @@ Working Lisp interpreter, but some key features not yet implemented.
### Project Target ### Project Target
The project target is to be able to run the [Wang algorithm for the propositional calculus](https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=52) given in chapter 8 of the *Lisp 1.5 Programmer's Manual*. When that runs, the project is as far as I am concerned feature complete. I may keep tinkering with it after that and I'll certainly accept pull requests which are in the spirit of the project (i.e. making Beowulf more usable, and/or implementing parts of Lisp 1.5 which I have not implemented), but this isn't intended to be a new language for doing real work; it's an The project target is to be able to run the [Wang algorithm for the propositional calculus](https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=52) given in chapter 8 of the *Lisp 1.5 Programmer's Manual*. When that runs, the project is as far as I am concerned feature complete. I may keep tinkering with it after that and I'll certainly accept pull requests which are in the spirit of the project (i.e. making Beowulf more usable, and/or implementing parts of Lisp 1.5 which I have not implemented), but this isn't intended to be a new language for doing real work; it's an educational and archaeological project, not serious engineering.
educational and archaeological project, not serious engineering.
Some `readline`-like functionality would be really useful, but my attempt to Some `readline`-like functionality would be really useful, but my attempt to integrate [JLine](https://github.com/jline/jline3) has not (yet) been successful.
integrate [JLine](https://github.com/jline/jline3) has not (yet) been successful.
An in-core structure editor would be an extremely nice thing, and I may well An in-core structure editor would be an extremely nice thing, and I may well implement one.
implement one.
You are of course welcome to fork the project and do whatever you like with it! You are of course welcome to fork the project and do whatever you like with it!
@ -77,7 +74,7 @@ You are of course welcome to fork the project and do whatever you like with it!
Invoke with Invoke with
java -jar target/uberjar/beowulf-0.3.1-standalone.jar --help java -jar target/uberjar/beowulf-0.3.0-standalone.jar --help
(Obviously, check your version number) (Obviously, check your version number)
@ -110,53 +107,53 @@ now be possible to reimplement them as `FEXPRs` and so the reader macro function
| Function | Type | Signature | Implementation | Documentation | | Function | Type | Signature | Implementation | Documentation |
|--------------|----------------|------------------|----------------|----------------------| |--------------|----------------|------------------|----------------|----------------------|
| NIL | Lisp variable | ? | | see manual pages <a href='#page22'>22</a>, <a href='#page69'>69</a> | | NIL | Lisp variable | ? | | The canonical empty list. See manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=22'>22</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=69'>69</a>s |
| T | Lisp variable | ? | | see manual pages <a href='#page22'>22</a>, <a href='#page69'>69</a> | | T | Lisp variable | ? | | The canonical true value. See manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=22'>22</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=69'>69</a> |
| F | Lisp variable | ? | | see manual pages <a href='#page22'>22</a>, <a href='#page69'>69</a> | | F | Lisp variable | ? | | The canonical false value. See manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=22'>22</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=69'>69</a> |
| ADD1 | Host lambda function | ? | | ? | | ADD1 | Host lambda function | x:number | | Add one to the number `x`. |
| AND | Host lambda function | ? | PREDICATE | `T` if and only if none of my `args` evaluate to either `F` or `NIL`, else `F`. In `beowulf.host` principally because I don't yet feel confident to define varargs functions in Lisp. | | AND | Host lambda function | expr* | PREDICATE | `T` if and only if none of my `args` evaluate to either `F` or `NIL`, else `F`. <br><br>In `beowulf.host` principally because I don't yet feel confident to define varargs functions in Lisp. |
| APPEND | Lisp lambda function | ? | | see manual pages <a href='#page11'>11</a>, <a href='#page61'>61</a> | | APPEND | Lisp lambda function | ? | | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=11'>11</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=61'>61</a> |
| APPLY | Host lambda function | ? | | Apply this `function` to these `arguments` in this `environment` and return the result. For bootstrapping, at least, a version of APPLY written in Clojure. All args are assumed to be symbols or `beowulf.cons-cell/ConsCell` objects. See page 13 of the Lisp 1.5 Programmers Manual. | | APPLY | Host lambda function | ? | | Apply this `function` to these `arguments` in this `environment` and return the result.<br><br>For bootstrapping, at least, a version of APPLY written in Clojure.<br><br>All args are assumed to be symbols or `beowulf.cons-cell/ConsCell` objects.<br><br>See page <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=13'>13</a> of the Lisp 1.5 Programmers Manual. |
| ASSOC | Lisp lambda function, Host lambda function | ? | ? | If a is an association list such as the one formed by PAIRLIS in the above example, then assoc will produce the first pair whose first term is x. Thus it is a table searching function. All args are assumed to be `beowulf.cons-cell/ConsCell` objects. See page 12 of the Lisp 1.5 Programmers Manual. **NOTE THAT** this function is overridden by an implementation in Lisp, but is currently still present for bootstrapping. | | ASSOC | Lisp lambda function, Host lambda function | a:list | ? | If a is an association list such as the one formed by PAIRLIS in the above example, then assoc will produce the first pair whose first term is x. Thus it is a table searching function. All args are assumed to be `beowulf.cons-cell/ConsCell` objects. See page <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=12'>12</a> of the Lisp 1.5 Programmers Manual.<br><br>**NOTE THAT** this function is overridden by an implementation in Lisp, but is currently still present for bootstrapping. |
| ATOM | Host lambda function | ? | PREDICATE | Returns `T` if and only if the argument `x` is bound to an atom; else `F`. It is not clear to me from the documentation whether `(ATOM 7)` should return `T` or `F`. I'm going to assume `T`. | | ATOM | Host lambda function | x:expr | PREDICATE | Returns `T` if and only if the argument `x` is bound to an atom; else `F`. It is not clear to me from the documentation whether `(ATOM 7)` should return `T` or `F`. I'm going to assume `T`. |
| CAR | Host lambda function | ? | | Return the item indicated by the first pointer of a pair. NIL is treated specially: the CAR of NIL is NIL. | | CAR | Host lambda function | list | | Return the item indicated by the first pointer of a pair. NIL is treated specially: the CAR of NIL is NIL. |
| CAAAAR | Lisp lambda function | ? | ? | ? | | CAAAAR | Lisp lambda function | list | ? | ? |
| CAAADR | Lisp lambda function | ? | ? | ? | | CAAADR | Lisp lambda function | list | ? | ? |
| CAAAR | Lisp lambda function | ? | ? | ? | | CAAAR | Lisp lambda function | list | ? | ? |
| CAADAR | Lisp lambda function | ? | ? | ? | | CAADAR | Lisp lambda function | list | ? | ? |
| CAADDR | Lisp lambda function | ? | ? | ? | | CAADDR | Lisp lambda function | list | ? | ? |
| CAADR | Lisp lambda function | ? | ? | ? | | CAADR | Lisp lambda function | list | ? | ? |
| CAAR | Lisp lambda function | ? | ? | ? | | CAAR | Lisp lambda function | list | ? | ? |
| CADAAR | Lisp lambda function | ? | ? | ? | | CADAAR | Lisp lambda function | list | ? | ? |
| CADADR | Lisp lambda function | ? | ? | ? | | CADADR | Lisp lambda function | list | ? | ? |
| CADAR | Lisp lambda function | ? | ? | ? | | CADAR | Lisp lambda function | list | ? | ? |
| CADDAR | Lisp lambda function | ? | ? | ? | | CADDAR | Lisp lambda function | list | ? | ? |
| CADDDR | Lisp lambda function | ? | ? | ? | | CADDDR | Lisp lambda function | list | ? | ? |
| CADDR | Lisp lambda function | ? | ? | ? | | CADDR | Lisp lambda function | list | ? | ? |
| CADR | Lisp lambda function | ? | ? | ? | | CADR | Lisp lambda function | list | ? | ? |
| CDAAAR | Lisp lambda function | ? | ? | ? | | CDAAAR | Lisp lambda function | list | ? | ? |
| CDAADR | Lisp lambda function | ? | ? | ? | | CDAADR | Lisp lambda function | list | ? | ? |
| CDAAR | Lisp lambda function | ? | ? | ? | | CDAAR | Lisp lambda function | list | ? | ? |
| CDADAR | Lisp lambda function | ? | ? | ? | | CDADAR | Lisp lambda function | list | ? | ? |
| CDADDR | Lisp lambda function | ? | ? | ? | | CDADDR | Lisp lambda function | list | ? | ? |
| CDADR | Lisp lambda function | ? | ? | ? | | CDADR | Lisp lambda function | list | ? | ? |
| CDAR | Lisp lambda function | ? | ? | ? | | CDAR | Lisp lambda function | list | ? | ? |
| CDDAAR | Lisp lambda function | ? | ? | ? | | CDDAAR | Lisp lambda function | list | ? | ? |
| CDDADR | Lisp lambda function | ? | ? | ? | | CDDADR | Lisp lambda function | list | ? | ? |
| CDDAR | Lisp lambda function | ? | ? | ? | | CDDAR | Lisp lambda function | list | ? | ? |
| CDDDAR | Lisp lambda function | ? | ? | ? | | CDDDAR | Lisp lambda function | list | ? | ? |
| CDDDDR | Lisp lambda function | ? | ? | ? | | CDDDDR | Lisp lambda function | list | ? | ? |
| CDDDR | Lisp lambda function | ? | ? | ? | | CDDDR | Lisp lambda function | list | ? | ? |
| CDDR | Lisp lambda function | ? | ? | ? | | CDDR | Lisp lambda function | list | ? | ? |
| CDR | Host lambda function | ? | | Return the item indicated by the second pointer of a pair. NIL is treated specially: the CDR of NIL is NIL. | | CDR | Host lambda function | list | | Return the item indicated by the second pointer of a pair. NIL is treated specially: the CDR of NIL is NIL. |
| CONS | Host lambda function | ? | | Construct a new instance of cons cell with this `car` and `cdr`. | | CONS | Host lambda function | expr, expr | | Construct a new instance of cons cell with this `car` and `cdr`. |
| CONSP | Host lambda function | ? | ? | Return `T` if object `o` is a cons cell, else `F`. **NOTE THAT** this is an extension function, not available in strct mode. I believe that Lisp 1.5 did not have any mechanism for testing whether an argument was, or was not, a cons cell. | | CONSP | Host lambda function | o:expr | ? | Return `T` if object `o` is a cons cell, else `F`.<br><br>**NOTE THAT** this is an extension function, not available in strict mode. I believe that Lisp 1.5 did not have any mechanism for testing whether an argument was, or was not, a cons cell. |
| COPY | Lisp lambda function | ? | | see manual pages <a href='#page62'>62</a> | | COPY | Lisp lambda function | ? | | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=62'>62</a> |
| DEFINE | Host lambda function | ? | PSEUDO-FUNCTION | Bootstrap-only version of `DEFINE` which, post boostrap, can be overwritten in LISP. The single argument to `DEFINE` should be an association list of symbols to lambda functions. See page 58 of the manual. | | DEFINE | Host lambda function | ? | PSEUDO-FUNCTION | Bootstrap-only version of `DEFINE` which, post boostrap, can be overwritten in LISP. The single argument to `DEFINE` should be an association list of symbols to lambda functions. See page <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=58'>58</a> of the manual. |
| DIFFERENCE | Host lambda function | ? | | ? | | DIFFERENCE | Host lambda function | x:number, y:number | | Returns the result of subtracting the number `y` from the number `x` |
| DIVIDE | Lisp lambda function | ? | | see manual pages <a href='#page26'>26</a>, <a href='#page64'>64</a> | | DIVIDE | Lisp lambda function | x:number, y:number | | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=26'>26</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=64'>64</a> |
| DOC | Host lambda function | ? | ? | Open the page for this `symbol` in the Lisp 1.5 manual, if known, in the default web browser. **NOTE THAT** this is an extension function, not available in strct mode. | | DOC | Host lambda function | ? | ? | Open the page for this `symbol` in the Lisp 1.5 manual, if known, in the default web browser.<br><br>**NOTE THAT** this is an extension function, not available in strct mode. |
| EFFACE | Lisp lambda function | ? | PSEUDO-FUNCTION | see manual pages <a href='#page63'>63</a> | | EFFACE | Lisp lambda function | ? | PSEUDO-FUNCTION | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=63'>63</a> |
| ERROR | Host lambda function | ? | PSEUDO-FUNCTION | Throw an error | | ERROR | Host lambda function | ? | PSEUDO-FUNCTION | Throw an error |
| EQ | Host lambda function | ? | PREDICATE | Returns `T` if and only if both `x` and `y` are bound to the same atom, else `NIL`. | | EQ | Host lambda function | ? | PREDICATE | Returns `T` if and only if both `x` and `y` are bound to the same atom, else `NIL`. |
| EQUAL | Host lambda function | ? | PREDICATE | This is a predicate that is true if its two arguments are identical S-expressions, and false if they are different. (The elementary predicate `EQ` is defined only for atomic arguments.) The definition of `EQUAL` is an example of a conditional expression inside a conditional expression. NOTE: returns `F` on failure, not `NIL` | | EQUAL | Host lambda function | ? | PREDICATE | This is a predicate that is true if its two arguments are identical S-expressions, and false if they are different. (The elementary predicate `EQ` is defined only for atomic arguments.) The definition of `EQUAL` is an example of a conditional expression inside a conditional expression. NOTE: returns `F` on failure, not `NIL` |
@ -164,50 +161,50 @@ now be possible to reimplement them as `FEXPRs` and so the reader macro function
| FACTORIAL | Lisp lambda function | ? | ? | ? | | FACTORIAL | Lisp lambda function | ? | ? | ? |
| FIXP | Host lambda function | ? | PREDICATE | ? | | FIXP | Host lambda function | ? | PREDICATE | ? |
| GENSYM | Host lambda function | ? | | Generate a unique symbol. | | GENSYM | Host lambda function | ? | | Generate a unique symbol. |
| GET | Host lambda function | ? | | From the manual: '`get` is somewhat like `prop`; however its value is car of the rest of the list if the `indicator` is found, and NIL otherwise.' It's clear that `GET` is expected to be defined in terms of `PROP`, but we can't implement `PROP` here because we lack `EVAL`; and we can't have `EVAL` here because both it and `APPLY` depends on `GET`. OK, It's worse than that: the statement of the definition of `GET` (and of) `PROP` on page 59 says that the first argument to each must be a list; But the in the definition of `ASSOC` on page 70, when `GET` is called its first argument is always an atom. Since it's `ASSOC` and `EVAL` which I need to make work, I'm going to assume that page 59 is wrong. | | GET | Host lambda function | ? | | From the manual: '`get` is somewhat like `prop`; however its value is car of the rest of the list if the `indicator` is found, and NIL otherwise.'<br><br>It's clear that `GET` is expected to be defined in terms of `PROP`, but we can't implement `PROP` here because we lack `EVAL`; and we can't have `EVAL` here because both it and `APPLY` depends on `GET`.<br><br>OK, It's worse than that: the statement of the definition of `GET` (and of) `PROP` on page <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=59'>59</a> says that the first argument to each must be a list; But the in the definition of `ASSOC` on page 70, when `GET` is called its first argument is always an atom. Since it's `ASSOC` and `EVAL` which I need to make work, I'm going to assume that page 59 is wrong. |
| GREATERP | Host lambda function | ? | PREDICATE | ? | | GREATERP | Host lambda function | ? | PREDICATE | ? |
| INTEROP | Host lambda function | ? | ? | ? | | INTEROP | Host lambda function | ? | ? | ? |
| INTERSECTION | Lisp lambda function | ? | ? | ? | | INTERSECTION | Lisp lambda function | ? | ? | ? |
| LENGTH | Lisp lambda function | ? | | see manual pages <a href='#page62'>62</a> | | LENGTH | Lisp lambda function | ? | | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=62'>62</a> |
| LESSP | Host lambda function | ? | PREDICATE | ? | | LESSP | Host lambda function | ? | PREDICATE | ? |
| MAPLIST | Lisp lambda function | ? | FUNCTIONAL | see manual pages <a href='#page20'>20</a>, <a href='#page21'>21</a>, <a href='#page63'>63</a> | | MAPLIST | Lisp lambda function | ? | FUNCTIONAL | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=20'>20</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=21'>21</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=63'>63</a> |
| MEMBER | Lisp lambda function | ? | PREDICATE | see manual pages <a href='#page11'>11</a>, <a href='#page62'>62</a> | | MEMBER | Lisp lambda function | ? | PREDICATE | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=11'>11</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=62'>62</a> |
| MINUSP | Lisp lambda function | ? | PREDICATE | see manual pages <a href='#page26'>26</a>, <a href='#page64'>64</a> | | MINUSP | Lisp lambda function | ? | PREDICATE | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=26'>26</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=64'>64</a> |
| NOT | Lisp lambda function | ? | PREDICATE | see manual pages <a href='#page21'>21</a>, <a href='#page23'>23</a>, <a href='#page58'>58</a> | | NOT | Lisp lambda function | ? | PREDICATE | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=21'>21</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=23'>23</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=58'>58</a> |
| NULL | Lisp lambda function | ? | PREDICATE | see manual pages <a href='#page11'>11</a>, <a href='#page57'>57</a> | | NULL | Lisp lambda function | ? | PREDICATE | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=11'>11</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=57'>57</a> |
| NUMBERP | Host lambda function | ? | PREDICATE | ? | | NUMBERP | Host lambda function | ? | PREDICATE | ? |
| OBLIST | Host lambda function | ? | | Return a list of the symbols currently bound on the object list. **NOTE THAT** in the Lisp 1.5 manual, footnote at the bottom of page 69, it implies that an argument can be passed but I'm not sure of the semantics of this. | | OBLIST | Host lambda function | ? | | Return a list of the symbols currently bound on the object list.<br><br>**NOTE THAT** in the Lisp 1.5 manual, footnote at the bottom of page <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=69'>69</a>, it implies that an argument can be passed but I'm not sure of the semantics of this. |
| ONEP | Lisp lambda function | ? | PREDICATE | see manual pages <a href='#page26'>26</a>, <a href='#page64'>64</a> | | ONEP | Lisp lambda function | ? | PREDICATE | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=26'>26</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=64'>64</a> |
| OR | Host lambda function | ? | PREDICATE | `T` if and only if at least one of my `args` evaluates to something other than either `F` or `NIL`, else `F`. In `beowulf.host` principally because I don't yet feel confident to define varargs functions in Lisp. | | OR | Host lambda function | ? | PREDICATE | `T` if and only if at least one of my `args` evaluates to something other than either `F` or `NIL`, else `F`.<br><br>In `beowulf.host` principally because I don't yet feel confident to define varargs functions in Lisp. |
| PAIR | Lisp lambda function | ? | | see manual pages <a href='#page60'>60</a> | | PAIR | Lisp lambda function | ? | | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=60'>60</a> |
| PAIRLIS | Lisp lambda function, Host lambda function | ? | ? | This function gives the list of pairs of corresponding elements of the lists `x` and `y`, and APPENDs this to the list `a`. The resultant list of pairs, which is like a table with two columns, is called an association list. Eessentially, it builds the environment on the stack, implementing shallow binding. All args are assumed to be `beowulf.cons-cell/ConsCell` objects. See page 12 of the Lisp 1.5 Programmers Manual. **NOTE THAT** this function is overridden by an implementation in Lisp, but is currently still present for bootstrapping. | | PAIRLIS | Lisp lambda function, Host lambda function | ? | ? | This function gives the list of pairs of corresponding elements of the lists `x` and `y`, and APPENDs this to the list `a`. The resultant list of pairs, which is like a table with two columns, is called an association list. Essentially, it builds the environment on the stack, implementing shallow binding.<br><br>All args are assumed to be `beowulf.cons-cell/ConsCell` objects. See page <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=12'>12</a> of the Lisp 1.5 Programmers Manual.<br><br>**NOTE THAT** this function is overridden by an implementation in Lisp, but is currently still present for bootstrapping. |
| PLUS | Host lambda function | ? | | ? | | PLUS | Host lambda function | ? | | ? |
| PRETTY | | ? | ? | ? | | PRETTY | | ? | ? | ? |
| PRINT | | ? | PSEUDO-FUNCTION | see manual pages <a href='#page65'>65</a>, <a href='#page84'>84</a> | | PRINT | | ? | PSEUDO-FUNCTION | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=65'>65</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=84'>84</a> |
| PROG | Host nlambda function | ? | | The accursed `PROG` feature. See page 71 of the manual. Lisp 1.5 introduced `PROG`, and most Lisps have been stuck with it ever since. It introduces imperative programming into what should be a pure functional language, and consequently it's going to be a pig to implement. Broadly, `PROG` is a variadic pseudo function called as a `FEXPR` (or possibly an `FSUBR`, although I'm not presently sure that would even work.) The arguments, which are unevaluated, are a list of forms, the first of which is expected to be a list of symbols which will be treated as names of variables within the program, and the rest of which (the 'program body') are either lists or symbols. Lists are treated as Lisp expressions which may be evaulated in turn. Symbols are treated as targets for the `GO` statement. **GO:** A `GO` statement takes the form of `(GO target)`, where `target` should be one of the symbols which occur at top level among that particular invocation of `PROG`s arguments. A `GO` statement may occur at top level in a PROG, or in a clause of a `COND` statement in a `PROG`, but not in a function called from the `PROG` statement. When a `GO` statement is evaluated, execution should transfer immediately to the expression which is the argument list immediately following the symbol which is its target. If the target is not found, an error with the code `A6` should be thrown. **RETURN:** A `RETURN` statement takes the form `(RETURN value)`, where `value` is any value. Following the evaluation of a `RETURN` statement, the `PROG` should immediately exit without executing any further expressions, returning the value. **SET and SETQ:** In addition to the above, if a `SET` or `SETQ` expression is encountered in any expression within the `PROG` body, it should affect not the global object list but instead only the local variables of the program. **COND:** In **strict** mode, when in normal execution, a `COND` statement none of whose clauses match should not return `NIL` but should throw an error with the code `A3`... *except* that inside a `PROG` body, it should not do so. *sigh*. **Flow of control:** Apart from the exceptions specified above, expressions in the program body are evaluated sequentially. If execution reaches the end of the program body, `NIL` is returned. Got all that? Good. | | PROG | Host nlambda function | ? | | The accursed `PROG` feature. See page <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=71'>71</a> of the manual.<br><br>Lisp 1.5 introduced `PROG`, and most Lisps have been stuck with it ever since. It introduces imperative programming into what should be a pure functional language, and consequently it's going to be a pig to implement. Broadly, `PROG` is a variadic pseudo function called as a `FEXPR` (or possibly an `FSUBR`, although I'm not presently sure that would even work.) The arguments, which are unevaluated, are a list of forms, the first of which is expected to be a list of symbols which will be treated as names of variables within the program, and the rest of which (the 'program body') are either lists or symbols. Lists are treated as Lisp expressions which may be evaulated in turn. Symbols are treated as targets for the `GO` statement. <ul><li>**GO:** A `GO` statement takes the form of `(GO target)`, where `target` should be one of the symbols which occur at top level among that particular invocation of `PROG`s arguments. A `GO` statement may occur at top level in a PROG, or in a clause of a `COND` statement in a `PROG`, but not in a function called from the `PROG` statement. When a `GO` statement is evaluated, execution should transfer immediately to the expression which is the argument list immediately following the symbol which is its target. If the target is not found, an error with the code `A6` should be thrown.</li><li>**RETURN:** A `RETURN` statement takes the form `(RETURN value)`, where `value` is any value. Following the evaluation of a `RETURN` statement, the `PROG` should immediately exit without executing any further expressions, returning the value.</li><li>**SET and SETQ:** In addition to the above, if a `SET` or `SETQ` expression is encountered in any expression within the `PROG` body, it should affect not the global object list but instead only the local variables of the program.</li><li>**COND:** In **strict** mode, when in normal execution, a `COND` statement none of whose clauses match should not return `NIL` but should throw an error with the code `A3`... *except* that inside a `PROG` body, it should not do so. *sigh*.</li></ul>**Flow of control:** Apart from the exceptions specified above, expressions in the program body are evaluated sequentially. If execution reaches the end of the program body, `NIL` is returned.<br><br>Got all that? Good. |
| PROP | Lisp lambda function | ? | FUNCTIONAL | see manual pages <a href='#page59'>59</a> | | PROP | Lisp lambda function | ? | FUNCTIONAL | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=59'>59</a> |
| QUOTE | Lisp lambda function | ? | | see manual pages <a href='#page10'>10</a>, <a href='#page22'>22</a>, <a href='#page71'>71</a> | | QUOTE | Lisp lambda function | ? | | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=10'>10</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=22'>22</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=71'>71</a> |
| QUOTIENT | Host lambda function | ? | | I'm not certain from the documentation whether Lisp 1.5 `QUOTIENT` returned the integer part of the quotient, or a realnum representing the whole quotient. I am for now implementing the latter. | | QUOTIENT | Host lambda function | ? | | I'm not certain from the documentation whether Lisp 1.5 `QUOTIENT` returned the integer part of the quotient, or a realnum representing the whole quotient. I am for now implementing the latter. |
| RANGE | Lisp lambda function | ? | ? | ? | | RANGE | Lisp lambda function | ? | ? | ? |
| READ | Host lambda function | ? | PSEUDO-FUNCTION | An implementation of a Lisp reader sufficient for bootstrapping; not necessarily the final Lisp reader. `input` should be either a string representation of a LISP expression, or else an input stream. A single form will be read. | | READ | Host lambda function | ? | PSEUDO-FUNCTION | An implementation of a Lisp reader sufficient for bootstrapping; not necessarily the final Lisp reader. `input` should be either a string representation of a LISP expression, or else an input stream. A single form will be read. |
| REMAINDER | Host lambda function | ? | | ? | | REMAINDER | Host lambda function | ? | | ? |
| REPEAT | Lisp lambda function | ? | ? | ? | | REPEAT | Lisp lambda function | ? | ? | ? |
| RPLACA | Host lambda function | ? | PSEUDO-FUNCTION | Replace the CAR pointer of this `cell` with this `value`. Dangerous, should really not exist, but does in Lisp 1.5 (and was important for some performance hacks in early Lisps) | | RPLACA | Host lambda function | ? | PSEUDO-FUNCTION | Replace the `CAR` pointer of this `cell` with this `value`. Dangerous, should really not exist, but does in Lisp 1.5 (and was important for some performance hacks in early Lisps) |
| RPLACD | Host lambda function | ? | PSEUDO-FUNCTION | Replace the CDR pointer of this `cell` with this `value`. Dangerous, should really not exist, but does in Lisp 1.5 (and was important for some performance hacks in early Lisps) | | RPLACD | Host lambda function | ? | PSEUDO-FUNCTION | Replace the `CDR` pointer of this `cell` with this `value`. Dangerous, should really not exist, but does in Lisp 1.5 (and was important for some performance hacks in early Lisps) |
| SEARCH | Lisp lambda function | ? | FUNCTIONAL | see manual pages <a href='#page63'>63</a> | | SEARCH | Lisp lambda function | ? | FUNCTIONAL | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=63'>63</a> |
| SET | Host lambda function | ? | PSEUDO-FUNCTION | Implementation of SET in Clojure. Add to the `oblist` a binding of the value of `var` to the value of `val`. NOTE WELL: this is not SETQ! | | SET | Host lambda function | ? | PSEUDO-FUNCTION | Implementation of SET in Clojure. Add to the `oblist` a binding of the value of `var` to the value of `val`.<br><br>**NOTE WELL**: this is not SETQ! |
| SUB1 | Lisp lambda function, Host lambda function | ? | | ? | | SUB1 | Lisp lambda function, Host lambda function | ? | | ? |
| SUB2 | Lisp lambda function | ? | ? | ? | | SUB2 | Lisp lambda function | ? | ? | ? |
| SUBLIS | Lisp lambda function | ? | | see manual pages <a href='#page12'>12</a>, <a href='#page61'>61</a> | | SUBLIS | Lisp lambda function | ? | | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=12'>12</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=61'>61</a> |
| SUBST | Lisp lambda function | ? | | see manual pages <a href='#page11'>11</a>, <a href='#page61'>61</a> | | SUBST | Lisp lambda function | ? | | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=11'>11</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=61'>61</a> |
| SYSIN | Host lambda function | ? | ? | Read the contents of the file at this `filename` into the object list. If the file is not a valid Beowulf sysout file, this will probably corrupt the system, you have been warned. File paths will be considered relative to the filepath set when starting Lisp. It is intended that sysout files can be read both from resources within the jar file, and from the file system. If a named file exists in both the file system and the resources, the file system will be preferred. **NOTE THAT** if the provided `filename` does not end with `.lsp` (which, if you're writing it from the Lisp REPL, it won't), the extension `.lsp` will be appended. **NOTE THAT** this is an extension function, not available in strct mode. | | SYSIN | Host lambda function | ? | ? | Read the contents of the file at this `filename` into the object list. If the file is not a valid Beowulf sysout file, this will probably corrupt the system, you have been warned. File paths will be considered relative to the filepath set when starting Lisp. It is intended that sysout files can be read both from resources within the jar file, and from the file system. If a named file exists in both the file system and the resources, the file system will be preferred.<br><br>**NOTE THAT** if the provided `filename` does not end with `.lsp` (which, if you're writing it from the Lisp REPL, it won't), the extension `.lsp` will be appended.<br><br>**NOTE THAT** this is an extension function, not available in strct mode. |
| SYSOUT | Host lambda function | ? | ? | Dump the current content of the object list to file. If no `filepath` is specified, a file name will be constructed of the symbol `Sysout` and the current date. File paths will be considered relative to the filepath set when starting Lisp. **NOTE THAT** this is an extension function, not available in strct mode. | | SYSOUT | Host lambda function | ? | ? | Dump the current content of the object list to file. If no `filepath` is specified, a file name will be constructed of the symbol `Sysout` and the current date. File paths will be considered relative to the filepath set when starting Lisp.<br><br>**NOTE THAT** this is an extension function, not available in strict mode. |
| TERPRI | | ? | PSEUDO-FUNCTION | see manual pages <a href='#page65'>65</a>, <a href='#page84'>84</a> | | TERPRI | | ? | PSEUDO-FUNCTION | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=65'>65</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=84'>84</a> |
| TIMES | Host lambda function | ? | | ? | | TIMES | Host lambda function | ? | | ? |
| TRACE | Host lambda function | ? | PSEUDO-FUNCTION | Add this `s` to the set of symbols currently being traced. If `s` is not a symbol or sequence of symbols, does nothing. | | TRACE | Host lambda function | ? | PSEUDO-FUNCTION | Add this `s` to the set of symbols currently being traced. If `s` is not a symbol or sequence of symbols, does nothing. |
| UNION | Lisp lambda function | ? | ? | ? | | UNION | Lisp lambda function | ? | ? | ? |
| UNTRACE | Host lambda function | ? | PSEUDO-FUNCTION | Remove this `s` from the set of symbols currently being traced. If `s` is not a symbol or sequence of symbols, does nothing. | | UNTRACE | Host lambda function | ? | PSEUDO-FUNCTION | Remove this `s` from the set of symbols currently being traced. If `s` is not a symbol or sequence of symbols, does nothing. |
| ZEROP | Lisp lambda function | ? | PREDICATE | see manual pages <a href='#page26'>26</a>, <a href='#page64'>64</a> | | ZEROP | Lisp lambda function | ? | PREDICATE | see manual pages <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=26'>26</a>, <a href='https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=64'>64</a> |
Functions described as 'Lisp function' above are defined in the default Functions described as 'Lisp function' above are defined in the default
sysout file, `resources/lisp1.5.lsp`, which will be loaded by default unless sysout file, `resources/lisp1.5.lsp`, which will be loaded by default unless
@ -219,8 +216,7 @@ over the Clojure implementations.
### Architectural plan ### Architectural plan
Not everything documented in this section is yet built. It indicates the Not everything documented in this section is yet built. It indicates the direction of travel and intended destination, not the current state.
direction of travel and intended destination, not the current state.
#### resources/lisp1.5.lsp #### resources/lisp1.5.lsp
@ -338,7 +334,7 @@ even has a working compiler!
### History resources ### History resources
I'm compiling a [list of links to historical documents on Lisp 1.5](https://simon-brooke.github.io/beowulf/docs/codox/further_reading.html). I'm compiling a [list of links to historical documents on Lisp 1.5](https://simon-brooke.github.io/beowulf/docs/further_reading.html).
## License ## License

View file

@ -961,15 +961,19 @@ But if eval is given (QUOTE X), X should not be evaluated. QUOTE is a special fo
that prevents its argument from being evaluated. that prevents its argument from being evaluated.
A special form differs from a function in two ways. Its arguments are not evaluated A special form differs from a function in two ways. Its arguments are not evaluated
before the special form sees them. COND, for example, has a very special way of before the special form sees them. COND, for example, has a very special way of
```
evaluating its arguments by using evcon. The second way which special forms differ evaluating its arguments by using evcon. The second way which special forms differ
from functions is that they may have an indefinite number of arguments. Special forms from functions is that they may have an indefinite number of arguments. Special forrrls
have indicators on their property lists called FEXPR and FSUBR for LISP -defined forms have indicators on their property lists called FEXPR and FSUBR for LISP -defined forms
and machine language coded forms, respectively. and machine language coded forms, respectively.
### 2.6 Programming for the Interpreter ```
2.6 Programming for the Interpreter
```
The purpose of this section is to help the programmer avoid certain common errors. The purpose of this section is to help the programmer avoid certain common errors.
Example 1: CAR Example 1
fn: CAR fn: CAR
args: ((A B)) args: ((A B))
The value is A. Note that the interpreter expects a list of arguments. The one argu- The value is A. Note that the interpreter expects a list of arguments. The one argu-
@ -977,11 +981,13 @@ ment for car is (A B). The extra pair of parentheses is necessary.
One could write (LAMBDA (X) (CAR X)) instead of just CAR. This is correct but One could write (LAMBDA (X) (CAR X)) instead of just CAR. This is correct but
unnecessary. unnecessary.
Example 2: CONS ```
Example 2
fn: CONS fn: CONS
args: (A (B. C)) args: (A (B. C))
The value is cons[a; cons[b; c]] = (A . (B . C)). The value is cons[^;(^. c)] = (A. (B. C)).
The print program will write this as (A B. C). The print program will write this as (A B. C).
```
Example (^3) - Example (^3) -
fn: CONS fn: CONS
@ -1715,7 +1721,6 @@ represented in storage only once,
The following simple example has been included to illustrate the exact construction The following simple example has been included to illustrate the exact construction
of list structures. Two types of list structures are shown, and a function for deriving of list structures. Two types of list structures are shown, and a function for deriving
one from the other is given in LISP. one from the other is given in LISP.
We assume that we have a list of the form We assume that we have a list of the form
n, = ((A B C) (D E F),... , (X Y z)), n, = ((A B C) (D E F),... , (X Y z)),
@ -2704,9 +2709,7 @@ If `deflist` or `define` is used twice on the same object with the same indicato
The function attrib concatenates its two arguments by changing the last element of its first argument to point to the second argument. Thus it is commonly used to tack something onto the end of a property list. The value of attrib is the second argument. The function attrib concatenates its two arguments by changing the last element of its first argument to point to the second argument. Thus it is commonly used to tack something onto the end of a property list. The value of attrib is the second argument.
For example For example
``` attrib[~~; (EXPR (LAMBDA (X) (COND ((ATOM X) X) (T (FF (CAR x))))))]
attrib[FF; (EXPR (LAMBDA (X) (COND ((ATOM X) X) (T (FF (CAR x))))))]
```
would put EXPR followed by the LAMBDA expression for FF onto the end of the prop- would put EXPR followed by the LAMBDA expression for FF onto the end of the prop-
erty list for FF. erty list for FF.

View file

@ -331,13 +331,13 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
109&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;else 109&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;else
</span><br/> </span><br/>
<span class="covered" title="5 out of 5 forms covered"> <span class="covered" title="3 out of 3 forms covered">
110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(beowulf.bootstrap&#x2F;EVAL&nbsp;expr 110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(beowulf.bootstrap&#x2F;EVAL&nbsp;expr
</span><br/> </span><br/>
<span class="partial" title="7 out of 11 forms covered"> <span class="covered" title="6 out of 6 forms covered">
111&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(merge-vars&nbsp;vars&nbsp;env) 111&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(merge-vars&nbsp;vars&nbsp;env)
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="partial" title="4 out of 8 forms covered">
112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;depth)))) 112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;depth))))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
@ -352,13 +352,13 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
116&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 116&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="2 out of 2 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
117&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Lisp&nbsp;1.5&nbsp;introduced&nbsp;`PROG`,&nbsp;and&nbsp;most&nbsp;Lisps&nbsp;have&nbsp;been&nbsp;stuck&nbsp;with&nbsp;it&nbsp;ever&nbsp; 117&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Lisp&nbsp;1.5&nbsp;introduced&nbsp;`PROG`,&nbsp;and&nbsp;most&nbsp;Lisps&nbsp;have&nbsp;been&nbsp;stuck&nbsp;with&nbsp;it&nbsp;ever&nbsp;
</span><br/> </span><br/>
<span class="partial" title="3 out of 7 forms covered"> <span class="covered" title="2 out of 2 forms covered">
118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;since.&nbsp;It&nbsp;introduces&nbsp;imperative&nbsp;programming&nbsp;into&nbsp;what&nbsp;should&nbsp;be&nbsp;a&nbsp;pure&nbsp; 118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;since.&nbsp;It&nbsp;introduces&nbsp;imperative&nbsp;programming&nbsp;into&nbsp;what&nbsp;should&nbsp;be&nbsp;a&nbsp;pure&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="partial" title="3 out of 7 forms covered">
119&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;functional&nbsp;language,&nbsp;and&nbsp;consequently&nbsp;it&#x27;s&nbsp;going&nbsp;to&nbsp;be&nbsp;a&nbsp;pig&nbsp;to&nbsp;implement. 119&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;functional&nbsp;language,&nbsp;and&nbsp;consequently&nbsp;it&#x27;s&nbsp;going&nbsp;to&nbsp;be&nbsp;a&nbsp;pig&nbsp;to&nbsp;implement.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
@ -757,7 +757,7 @@
<span class="covered" title="5 out of 5 forms covered"> <span class="covered" title="5 out of 5 forms covered">
251&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[lisp-fn&nbsp;(value&nbsp;function-symbol&nbsp;&#x27;(EXPR&nbsp;FEXPR)) 251&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[lisp-fn&nbsp;(value&nbsp;function-symbol&nbsp;&#x27;(EXPR&nbsp;FEXPR))
</span><br/> </span><br/>
<span class="partial" title="7 out of 8 forms covered"> <span class="partial" title="6 out of 8 forms covered">
252&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;args&#x27;&nbsp;(cond&nbsp;(=&nbsp;NIL&nbsp;args)&nbsp;args 252&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;args&#x27;&nbsp;(cond&nbsp;(=&nbsp;NIL&nbsp;args)&nbsp;args
</span><br/> </span><br/>
<span class="partial" title="3 out of 4 forms covered"> <span class="partial" title="3 out of 4 forms covered">

View file

@ -259,7 +259,7 @@
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
085&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if 085&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if
</span><br/> </span><br/>
<span class="partial" title="11 out of 13 forms covered"> <span class="partial" title="10 out of 13 forms covered">
086&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(or 086&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(or
</span><br/> </span><br/>
<span class="covered" title="4 out of 4 forms covered"> <span class="covered" title="4 out of 4 forms covered">
@ -445,22 +445,22 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
147&nbsp;&nbsp;&nbsp;&nbsp;clojure.lang.Counted 147&nbsp;&nbsp;&nbsp;&nbsp;clojure.lang.Counted
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="not-covered" title="0 out of 3 forms covered">
148&nbsp;&nbsp;&nbsp;&nbsp;(count&nbsp;[this]&nbsp;(loop&nbsp;[cell&nbsp;this 148&nbsp;&nbsp;&nbsp;&nbsp;(count&nbsp;[this]&nbsp;(loop&nbsp;[cell&nbsp;this
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
149&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;1] 149&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;1]
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="not-covered" title="0 out of 1 forms covered">
150&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if 150&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if
</span><br/> </span><br/>
<span class="covered" title="11 out of 11 forms covered"> <span class="not-covered" title="0 out of 11 forms covered">
151&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(and&nbsp;(coll?&nbsp;(.getCdr&nbsp;cell))&nbsp;(not=&nbsp;NIL&nbsp;(.getCdr&nbsp;cell))) 151&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(and&nbsp;(coll?&nbsp;(.getCdr&nbsp;cell))&nbsp;(not=&nbsp;NIL&nbsp;(.getCdr&nbsp;cell)))
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="not-covered" title="0 out of 1 forms covered">
152&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(recur&nbsp;(.getCdr&nbsp;cell)&nbsp;(inc&nbsp;result)) 152&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(recur&nbsp;(.getCdr&nbsp;cell)&nbsp;(inc&nbsp;result))
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="not-covered" title="0 out of 1 forms covered">
153&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result))) 153&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result)))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">

View file

@ -154,10 +154,10 @@
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
050&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:default&nbsp;default-sysout 050&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:default&nbsp;default-sysout
</span><br/> </span><br/>
<span class="partial" title="7 out of 8 forms covered"> <span class="partial" title="3 out of 8 forms covered">
051&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:validate&nbsp;[#(and 051&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:validate&nbsp;[#(and
</span><br/> </span><br/>
<span class="covered" title="4 out of 4 forms covered"> <span class="not-covered" title="0 out of 4 forms covered">
052&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.exists&nbsp;(io&#x2F;file&nbsp;%)) 052&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.exists&nbsp;(io&#x2F;file&nbsp;%))
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <span class="not-covered" title="0 out of 3 forms covered">
@ -170,40 +170,40 @@
055&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&quot;-s&quot;&nbsp;&quot;--strict&quot;&nbsp;&quot;Strictly&nbsp;interpret&nbsp;the&nbsp;Lisp&nbsp;1.5&nbsp;language,&nbsp;without&nbsp;extensions.&quot;] 055&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&quot;-s&quot;&nbsp;&quot;--strict&quot;&nbsp;&quot;Strictly&nbsp;interpret&nbsp;the&nbsp;Lisp&nbsp;1.5&nbsp;language,&nbsp;without&nbsp;extensions.&quot;]
</span><br/> </span><br/>
<span class="covered" title="4 out of 4 forms covered"> <span class="covered" title="4 out of 4 forms covered">
056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&quot;-t&quot;&nbsp;&quot;--time&quot;&nbsp;&quot;Time&nbsp;evaluations.&quot;] 056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&quot;-t&quot;&nbsp;&quot;--time&quot;&nbsp;&quot;Time&nbsp;evaluations.&quot;]])
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
057&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&quot;-x&quot;&nbsp;&quot;--testing&quot;&nbsp;&quot;Disable&nbsp;the&nbsp;jline&nbsp;reader&nbsp;-&nbsp;useful&nbsp;when&nbsp;piping&nbsp;input.&quot;]])
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
058&nbsp;&nbsp; 057&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
059&nbsp;&nbsp;(defn-&nbsp;re&nbsp; 058&nbsp;&nbsp;(defn-&nbsp;re&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
060&nbsp;&nbsp;&nbsp;&nbsp;&quot;Like&nbsp;REPL,&nbsp;but&nbsp;it&nbsp;isn&#x27;t&nbsp;a&nbsp;loop&nbsp;and&nbsp;doesn&#x27;t&nbsp;print.&quot; 059&nbsp;&nbsp;&nbsp;&nbsp;&quot;Like&nbsp;REPL,&nbsp;but&nbsp;it&nbsp;isn&#x27;t&nbsp;a&nbsp;loop&nbsp;and&nbsp;doesn&#x27;t&nbsp;print.&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
061&nbsp;&nbsp;&nbsp;&nbsp;[input] 060&nbsp;&nbsp;&nbsp;&nbsp;[input]
</span><br/> </span><br/>
<span class="covered" title="7 out of 7 forms covered"> <span class="covered" title="7 out of 7 forms covered">
062&nbsp;&nbsp;&nbsp;&nbsp;(EVAL&nbsp;(READ&nbsp;input)&nbsp;NIL&nbsp;0)) 061&nbsp;&nbsp;&nbsp;&nbsp;(EVAL&nbsp;(READ&nbsp;input)&nbsp;NIL&nbsp;0))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
063&nbsp;&nbsp; 062&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
064&nbsp;&nbsp;(defn&nbsp;repl 063&nbsp;&nbsp;(defn&nbsp;repl
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
065&nbsp;&nbsp;&nbsp;&nbsp;&quot;Read&#x2F;eval&#x2F;print&nbsp;loop.&quot; 064&nbsp;&nbsp;&nbsp;&nbsp;&quot;Read&#x2F;eval&#x2F;print&nbsp;loop.&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
066&nbsp;&nbsp;&nbsp;&nbsp;[prompt] 065&nbsp;&nbsp;&nbsp;&nbsp;[prompt]
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
067&nbsp;&nbsp;&nbsp;&nbsp;(loop&nbsp;[]&nbsp; 066&nbsp;&nbsp;&nbsp;&nbsp;(loop&nbsp;[]
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
067&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(print&nbsp;prompt)
</span><br/> </span><br/>
<span class="covered" title="2 out of 2 forms covered"> <span class="covered" title="2 out of 2 forms covered">
068&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(flush) 068&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(flush)
@ -211,8 +211,8 @@
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
069&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(try 069&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(try
</span><br/> </span><br/>
<span class="covered" title="10 out of 10 forms covered"> <span class="covered" title="9 out of 9 forms covered">
070&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if-let&nbsp;[input&nbsp;(trim&nbsp;(read-from-console&nbsp;prompt))] 070&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if-let&nbsp;[input&nbsp;(trim&nbsp;(read-from-console))]
</span><br/> </span><br/>
<span class="covered" title="4 out of 4 forms covered"> <span class="covered" title="4 out of 4 forms covered">
071&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(=&nbsp;input&nbsp;stop-word) 071&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(=&nbsp;input&nbsp;stop-word)
@ -259,7 +259,7 @@
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
085&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data 085&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data
</span><br/> </span><br/>
<span class="covered" title="6 out of 6 forms covered"> <span class="partial" title="5 out of 6 forms covered">
086&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(case&nbsp;(:cause&nbsp;data) 086&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(case&nbsp;(:cause&nbsp;data)
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 5 forms covered"> <span class="not-covered" title="0 out of 5 forms covered">
@ -316,13 +316,13 @@
<span class="covered" title="6 out of 6 forms covered"> <span class="covered" title="6 out of 6 forms covered">
104&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;Síðe&nbsp;&quot;&nbsp;(System&#x2F;getProperty&nbsp;&quot;beowulf.version&quot;)&nbsp;&quot;\n&quot;)) 104&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;Síðe&nbsp;&quot;&nbsp;(System&#x2F;getProperty&nbsp;&quot;beowulf.version&quot;)&nbsp;&quot;\n&quot;))
</span><br/> </span><br/>
<span class="covered" title="2 out of 2 forms covered"> <span class="partial" title="1 out of 2 forms covered">
105&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when 105&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when
</span><br/> </span><br/>
<span class="covered" title="5 out of 5 forms covered"> <span class="covered" title="5 out of 5 forms covered">
106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:help&nbsp;(:options&nbsp;args)) 106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:help&nbsp;(:options&nbsp;args))
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="not-covered" title="0 out of 3 forms covered">
107&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:summary&nbsp;args)) 107&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(:summary&nbsp;args))
</span><br/> </span><br/>
<span class="covered" title="5 out of 5 forms covered"> <span class="covered" title="5 out of 5 forms covered">
@ -358,8 +358,8 @@
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(try 118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(try
</span><br/> </span><br/>
<span class="covered" title="7 out of 7 forms covered"> <span class="covered" title="10 out of 10 forms covered">
119&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(repl&nbsp;(:prompt&nbsp;(:options&nbsp;args))) 119&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(repl&nbsp;(str&nbsp;(:prompt&nbsp;(:options&nbsp;args))&nbsp;&quot;&nbsp;&quot;))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
120&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(catch 120&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(catch

File diff suppressed because it is too large Load diff

View file

@ -334,13 +334,13 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reference.&quot; 110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reference.&quot;
</span><br/> </span><br/>
<span class="partial" title="1 out of 3 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
111&nbsp;&nbsp;&nbsp;&nbsp;([entry] 111&nbsp;&nbsp;&nbsp;&nbsp;([entry]
</span><br/> </span><br/>
<span class="partial" title="9 out of 12 forms covered"> <span class="partial" title="9 out of 12 forms covered">
112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(or&nbsp;(resolve-subr&nbsp;entry&nbsp;&#x27;SUBR) 112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(or&nbsp;(resolve-subr&nbsp;entry&nbsp;&#x27;SUBR)
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <span class="partial" title="1 out of 6 forms covered">
113&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(resolve-subr&nbsp;entry&nbsp;&#x27;FSUBR))) 113&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(resolve-subr&nbsp;entry&nbsp;&#x27;FSUBR)))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">

View file

@ -133,8 +133,8 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
043&nbsp;&nbsp;&nbsp;&nbsp;&quot;Command&nbsp;line&nbsp;options&nbsp;from&nbsp;invocation.&quot; 043&nbsp;&nbsp;&nbsp;&nbsp;&quot;Command&nbsp;line&nbsp;options&nbsp;from&nbsp;invocation.&quot;
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="covered" title="1 out of 1 forms covered">
044&nbsp;&nbsp;&nbsp;&nbsp;{:testing&nbsp;true}) 044&nbsp;&nbsp;&nbsp;&nbsp;{})
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
045&nbsp;&nbsp; 045&nbsp;&nbsp;

View file

@ -50,319 +50,283 @@
015&nbsp;&nbsp;&nbsp;&nbsp;switch.&quot; 015&nbsp;&nbsp;&nbsp;&nbsp;switch.&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
016&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[beowulf.oblist&nbsp;:refer&nbsp;[*options*]] 016&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;;;&nbsp;[beowulf.reader.char-reader&nbsp;:refer&nbsp;[read-chars]]
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[beowulf.reader.char-reader&nbsp;:refer&nbsp;[read-chars]] 017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[beowulf.reader.generate&nbsp;:refer&nbsp;[generate]]
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[beowulf.reader.generate&nbsp;:refer&nbsp;[generate]] 018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[beowulf.reader.parser&nbsp;:refer&nbsp;[parse]]
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[beowulf.reader.parser&nbsp;:refer&nbsp;[parse]] 019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[beowulf.reader.simplify&nbsp;:refer&nbsp;[simplify]]
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[beowulf.reader.simplify&nbsp;:refer&nbsp;[simplify]] 020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clojure.string&nbsp;:refer&nbsp;[join&nbsp;split&nbsp;starts-with?&nbsp;trim]])
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[clojure.string&nbsp;:refer&nbsp;[join&nbsp;split&nbsp;starts-with?&nbsp;trim]]) 021&nbsp;&nbsp;&nbsp;&nbsp;(:import&nbsp;[java.io&nbsp;InputStream]
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
022&nbsp;&nbsp;&nbsp;&nbsp;(:import&nbsp;[instaparse.gll&nbsp;Failure] 022&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[instaparse.gll&nbsp;Failure]))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
023&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[java.io&nbsp;InputStream]))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
024&nbsp;&nbsp; 023&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
025&nbsp;&nbsp;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 024&nbsp;&nbsp;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
026&nbsp;&nbsp;;;; 025&nbsp;&nbsp;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
027&nbsp;&nbsp;;;;&nbsp;This&nbsp;file&nbsp;provides&nbsp;the&nbsp;reader&nbsp;required&nbsp;for&nbsp;boostrapping.&nbsp;It&#x27;s&nbsp;not&nbsp;a&nbsp;bad 026&nbsp;&nbsp;;;;&nbsp;This&nbsp;file&nbsp;provides&nbsp;the&nbsp;reader&nbsp;required&nbsp;for&nbsp;boostrapping.&nbsp;It&#x27;s&nbsp;not&nbsp;a&nbsp;bad
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
028&nbsp;&nbsp;;;;&nbsp;reader&nbsp;-&nbsp;it&nbsp;provides&nbsp;feedback&nbsp;on&nbsp;errors&nbsp;found&nbsp;in&nbsp;the&nbsp;input&nbsp;-&nbsp;but&nbsp;it&nbsp;isn&#x27;t 027&nbsp;&nbsp;;;;&nbsp;reader&nbsp;-&nbsp;it&nbsp;provides&nbsp;feedback&nbsp;on&nbsp;errors&nbsp;found&nbsp;in&nbsp;the&nbsp;input&nbsp;-&nbsp;but&nbsp;it&nbsp;isn&#x27;t
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
029&nbsp;&nbsp;;;;&nbsp;the&nbsp;real&nbsp;Lisp&nbsp;reader. 028&nbsp;&nbsp;;;;&nbsp;the&nbsp;real&nbsp;Lisp&nbsp;reader.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
030&nbsp;&nbsp;;;; 029&nbsp;&nbsp;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
031&nbsp;&nbsp;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 030&nbsp;&nbsp;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
032&nbsp;&nbsp;;;; 031&nbsp;&nbsp;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
033&nbsp;&nbsp;;;;&nbsp;Copyright&nbsp;(C)&nbsp;2022-2023&nbsp;Simon&nbsp;Brooke 032&nbsp;&nbsp;;;;&nbsp;Copyright&nbsp;(C)&nbsp;2022-2023&nbsp;Simon&nbsp;Brooke
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
034&nbsp;&nbsp;;;; 033&nbsp;&nbsp;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
035&nbsp;&nbsp;;;;&nbsp;This&nbsp;program&nbsp;is&nbsp;free&nbsp;software;&nbsp;you&nbsp;can&nbsp;redistribute&nbsp;it&nbsp;and&#x2F;or 034&nbsp;&nbsp;;;;&nbsp;This&nbsp;program&nbsp;is&nbsp;free&nbsp;software;&nbsp;you&nbsp;can&nbsp;redistribute&nbsp;it&nbsp;and&#x2F;or
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
036&nbsp;&nbsp;;;;&nbsp;modify&nbsp;it&nbsp;under&nbsp;the&nbsp;terms&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License 035&nbsp;&nbsp;;;;&nbsp;modify&nbsp;it&nbsp;under&nbsp;the&nbsp;terms&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
037&nbsp;&nbsp;;;;&nbsp;as&nbsp;published&nbsp;by&nbsp;the&nbsp;Free&nbsp;Software&nbsp;Foundation;&nbsp;either&nbsp;version&nbsp;2 036&nbsp;&nbsp;;;;&nbsp;as&nbsp;published&nbsp;by&nbsp;the&nbsp;Free&nbsp;Software&nbsp;Foundation;&nbsp;either&nbsp;version&nbsp;2
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
038&nbsp;&nbsp;;;;&nbsp;of&nbsp;the&nbsp;License,&nbsp;or&nbsp;(at&nbsp;your&nbsp;option)&nbsp;any&nbsp;later&nbsp;version. 037&nbsp;&nbsp;;;;&nbsp;of&nbsp;the&nbsp;License,&nbsp;or&nbsp;(at&nbsp;your&nbsp;option)&nbsp;any&nbsp;later&nbsp;version.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
039&nbsp;&nbsp;;;;&nbsp; 038&nbsp;&nbsp;;;;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
040&nbsp;&nbsp;;;;&nbsp;This&nbsp;program&nbsp;is&nbsp;distributed&nbsp;in&nbsp;the&nbsp;hope&nbsp;that&nbsp;it&nbsp;will&nbsp;be&nbsp;useful, 039&nbsp;&nbsp;;;;&nbsp;This&nbsp;program&nbsp;is&nbsp;distributed&nbsp;in&nbsp;the&nbsp;hope&nbsp;that&nbsp;it&nbsp;will&nbsp;be&nbsp;useful,
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
041&nbsp;&nbsp;;;;&nbsp;but&nbsp;WITHOUT&nbsp;ANY&nbsp;WARRANTY;&nbsp;without&nbsp;even&nbsp;the&nbsp;implied&nbsp;warranty&nbsp;of 040&nbsp;&nbsp;;;;&nbsp;but&nbsp;WITHOUT&nbsp;ANY&nbsp;WARRANTY;&nbsp;without&nbsp;even&nbsp;the&nbsp;implied&nbsp;warranty&nbsp;of
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
042&nbsp;&nbsp;;;;&nbsp;MERCHANTABILITY&nbsp;or&nbsp;FITNESS&nbsp;FOR&nbsp;A&nbsp;PARTICULAR&nbsp;PURPOSE.&nbsp;&nbsp;See&nbsp;the 041&nbsp;&nbsp;;;;&nbsp;MERCHANTABILITY&nbsp;or&nbsp;FITNESS&nbsp;FOR&nbsp;A&nbsp;PARTICULAR&nbsp;PURPOSE.&nbsp;&nbsp;See&nbsp;the
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
043&nbsp;&nbsp;;;;&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License&nbsp;for&nbsp;more&nbsp;details. 042&nbsp;&nbsp;;;;&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License&nbsp;for&nbsp;more&nbsp;details.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
044&nbsp;&nbsp;;;;&nbsp; 043&nbsp;&nbsp;;;;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
045&nbsp;&nbsp;;;;&nbsp;You&nbsp;should&nbsp;have&nbsp;received&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License 044&nbsp;&nbsp;;;;&nbsp;You&nbsp;should&nbsp;have&nbsp;received&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
046&nbsp;&nbsp;;;;&nbsp;along&nbsp;with&nbsp;this&nbsp;program;&nbsp;if&nbsp;not,&nbsp;write&nbsp;to&nbsp;the&nbsp;Free&nbsp;Software 045&nbsp;&nbsp;;;;&nbsp;along&nbsp;with&nbsp;this&nbsp;program;&nbsp;if&nbsp;not,&nbsp;write&nbsp;to&nbsp;the&nbsp;Free&nbsp;Software
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
047&nbsp;&nbsp;;;;&nbsp;Foundation,&nbsp;Inc.,&nbsp;51&nbsp;Franklin&nbsp;Street,&nbsp;Fifth&nbsp;Floor,&nbsp;Boston,&nbsp;MA&nbsp;&nbsp;02110-1301,&nbsp;USA. 046&nbsp;&nbsp;;;;&nbsp;Foundation,&nbsp;Inc.,&nbsp;51&nbsp;Franklin&nbsp;Street,&nbsp;Fifth&nbsp;Floor,&nbsp;Boston,&nbsp;MA&nbsp;&nbsp;02110-1301,&nbsp;USA.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
048&nbsp;&nbsp;;;; 047&nbsp;&nbsp;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
049&nbsp;&nbsp;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 048&nbsp;&nbsp;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
050&nbsp;&nbsp; 049&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
051&nbsp;&nbsp;(defn&nbsp;strip-line-comments 050&nbsp;&nbsp;(defn&nbsp;strip-line-comments
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
052&nbsp;&nbsp;&nbsp;&nbsp;&quot;Strip&nbsp;blank&nbsp;lines&nbsp;and&nbsp;comment&nbsp;lines&nbsp;from&nbsp;this&nbsp;string&nbsp;`s`,&nbsp;expected&nbsp;to 051&nbsp;&nbsp;&nbsp;&nbsp;&quot;Strip&nbsp;blank&nbsp;lines&nbsp;and&nbsp;comment&nbsp;lines&nbsp;from&nbsp;this&nbsp;string&nbsp;`s`,&nbsp;expected&nbsp;to
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
053&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;be&nbsp;Lisp&nbsp;source.&quot; 052&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;be&nbsp;Lisp&nbsp;source.&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
054&nbsp;&nbsp;&nbsp;&nbsp;[^String&nbsp;s] 053&nbsp;&nbsp;&nbsp;&nbsp;[^String&nbsp;s]
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="covered" title="3 out of 3 forms covered">
055&nbsp;&nbsp;&nbsp;&nbsp;(join&nbsp;&quot;\n&quot; 054&nbsp;&nbsp;&nbsp;&nbsp;(join&nbsp;&quot;\n&quot;
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="covered" title="3 out of 3 forms covered">
056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(remove 055&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(remove
</span><br/> </span><br/>
<span class="covered" title="9 out of 9 forms covered"> <span class="covered" title="9 out of 9 forms covered">
057&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(or&nbsp;(empty?&nbsp;%) 056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(or&nbsp;(empty?&nbsp;%)
</span><br/> </span><br/>
<span class="covered" title="4 out of 4 forms covered"> <span class="covered" title="4 out of 4 forms covered">
058&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(starts-with?&nbsp;(trim&nbsp;%)&nbsp;&quot;;;&quot;)) 057&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(starts-with?&nbsp;(trim&nbsp;%)&nbsp;&quot;;;&quot;))
</span><br/> </span><br/>
<span class="covered" title="4 out of 4 forms covered"> <span class="covered" title="4 out of 4 forms covered">
059&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(split&nbsp;s&nbsp;#&quot;\n&quot;)))) 058&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(split&nbsp;s&nbsp;#&quot;\n&quot;))))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
060&nbsp;&nbsp; 059&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
061&nbsp;&nbsp;(defn&nbsp;number-lines 060&nbsp;&nbsp;(defn&nbsp;number-lines
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
062&nbsp;&nbsp;&nbsp;&nbsp;([^String&nbsp;s] 061&nbsp;&nbsp;&nbsp;&nbsp;([^String&nbsp;s]
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <span class="not-covered" title="0 out of 4 forms covered">
063&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(number-lines&nbsp;s&nbsp;nil)) 062&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(number-lines&nbsp;s&nbsp;nil))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
064&nbsp;&nbsp;&nbsp;&nbsp;([^String&nbsp;s&nbsp;^Failure&nbsp;e] 063&nbsp;&nbsp;&nbsp;&nbsp;([^String&nbsp;s&nbsp;^Failure&nbsp;e]
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <span class="not-covered" title="0 out of 4 forms covered">
065&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[l&nbsp;(-&gt;&nbsp;e&nbsp;:line) 064&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[l&nbsp;(-&gt;&nbsp;e&nbsp;:line)
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <span class="not-covered" title="0 out of 3 forms covered">
066&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;(-&gt;&nbsp;e&nbsp;:column)] 065&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;(-&gt;&nbsp;e&nbsp;:column)]
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 3 forms covered"> <span class="not-covered" title="0 out of 3 forms covered">
067&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(join&nbsp;&quot;\n&quot; 066&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(join&nbsp;&quot;\n&quot;
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 11 forms covered"> <span class="not-covered" title="0 out of 11 forms covered">
068&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(map&nbsp;#(str&nbsp;(format&nbsp;&quot;%5d&nbsp;%s&quot;&nbsp;(inc&nbsp;%1)&nbsp;%2) 067&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(map&nbsp;#(str&nbsp;(format&nbsp;&quot;%5d&nbsp;%s&quot;&nbsp;(inc&nbsp;%1)&nbsp;%2)
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 6 forms covered"> <span class="not-covered" title="0 out of 6 forms covered">
069&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when&nbsp;(=&nbsp;l&nbsp;(inc&nbsp;%1)) 068&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when&nbsp;(=&nbsp;l&nbsp;(inc&nbsp;%1))
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 11 forms covered"> <span class="not-covered" title="0 out of 11 forms covered">
070&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;\n&quot;&nbsp;(apply&nbsp;str&nbsp;(repeat&nbsp;c&nbsp;&quot;&nbsp;&quot;))&nbsp;&quot;^&quot;))) 069&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str&nbsp;&quot;\n&quot;&nbsp;(apply&nbsp;str&nbsp;(repeat&nbsp;c&nbsp;&quot;&nbsp;&quot;))&nbsp;&quot;^&quot;)))
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 2 forms covered"> <span class="not-covered" title="0 out of 2 forms covered">
071&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(range) 070&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(range)
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 4 forms covered"> <span class="not-covered" title="0 out of 4 forms covered">
072&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(split&nbsp;s&nbsp;#&quot;\n&quot;)))))) 071&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(split&nbsp;s&nbsp;#&quot;\n&quot;))))))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
073&nbsp;&nbsp; 072&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
074&nbsp;&nbsp;(defn&nbsp;gsp 073&nbsp;&nbsp;(defn&nbsp;gsp
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
075&nbsp;&nbsp;&nbsp;&nbsp;&quot;Shortcut&nbsp;macro&nbsp;-&nbsp;the&nbsp;internals&nbsp;of&nbsp;read;&nbsp;or,&nbsp;if&nbsp;you&nbsp;like,&nbsp;read-string. 074&nbsp;&nbsp;&nbsp;&nbsp;&quot;Shortcut&nbsp;macro&nbsp;-&nbsp;the&nbsp;internals&nbsp;of&nbsp;read;&nbsp;or,&nbsp;if&nbsp;you&nbsp;like,&nbsp;read-string.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
076&nbsp;&nbsp;&nbsp;&nbsp;Argument&nbsp;`s`&nbsp;should&nbsp;be&nbsp;a&nbsp;string&nbsp;representation&nbsp;of&nbsp;a&nbsp;valid&nbsp;Lisp 075&nbsp;&nbsp;&nbsp;&nbsp;Argument&nbsp;`s`&nbsp;should&nbsp;be&nbsp;a&nbsp;string&nbsp;representation&nbsp;of&nbsp;a&nbsp;valid&nbsp;Lisp
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
077&nbsp;&nbsp;&nbsp;&nbsp;expression.&quot; 076&nbsp;&nbsp;&nbsp;&nbsp;expression.&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
078&nbsp;&nbsp;&nbsp;&nbsp;[s] 077&nbsp;&nbsp;&nbsp;&nbsp;[s]
</span><br/> </span><br/>
<span class="covered" title="4 out of 4 forms covered"> <span class="covered" title="4 out of 4 forms covered">
079&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[source&nbsp;(strip-line-comments&nbsp;s) 078&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[source&nbsp;(strip-line-comments&nbsp;s)
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="covered" title="3 out of 3 forms covered">
080&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parse-tree&nbsp;(parse&nbsp;source)] 079&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parse-tree&nbsp;(parse&nbsp;source)]
</span><br/> </span><br/>
<span class="covered" title="5 out of 5 forms covered"> <span class="covered" title="5 out of 5 forms covered">
081&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(instance?&nbsp;Failure&nbsp;parse-tree) 080&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(instance?&nbsp;Failure&nbsp;parse-tree)
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 8 forms covered"> <span class="not-covered" title="0 out of 8 forms covered">
082&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(doall&nbsp;(println&nbsp;(number-lines&nbsp;source&nbsp;parse-tree)) 081&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(doall&nbsp;(println&nbsp;(number-lines&nbsp;source&nbsp;parse-tree))
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 9 forms covered"> <span class="not-covered" title="0 out of 9 forms covered">
083&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(throw&nbsp;(ex-info&nbsp;&quot;Ne&nbsp;can&nbsp;forstande&nbsp;&quot;&nbsp;(assoc&nbsp;parse-tree&nbsp;:source&nbsp;source)))) 082&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(throw&nbsp;(ex-info&nbsp;&quot;Ne&nbsp;can&nbsp;forstande&nbsp;&quot;&nbsp;(assoc&nbsp;parse-tree&nbsp;:source&nbsp;source))))
</span><br/> </span><br/>
<span class="covered" title="5 out of 5 forms covered"> <span class="covered" title="5 out of 5 forms covered">
084&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(generate&nbsp;(simplify&nbsp;parse-tree))))) 083&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(generate&nbsp;(simplify&nbsp;parse-tree)))))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
085&nbsp;&nbsp; 084&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
086&nbsp;&nbsp;(defn-&nbsp;dummy-read-chars&nbsp;[prompt] 085&nbsp;&nbsp;(defn&nbsp;read-from-console
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
086&nbsp;&nbsp;&nbsp;&nbsp;&quot;Attempt&nbsp;to&nbsp;read&nbsp;a&nbsp;complete&nbsp;lisp&nbsp;expression&nbsp;from&nbsp;the&nbsp;console.&nbsp;NOTE&nbsp;that&nbsp;this
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
087&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;will&nbsp;only&nbsp;really&nbsp;work&nbsp;for&nbsp;S-Expressions,&nbsp;not&nbsp;M-Expressions.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
088&nbsp;&nbsp;&nbsp;&nbsp;[]
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="covered" title="3 out of 3 forms covered">
087&nbsp;&nbsp;&nbsp;&nbsp;(loop&nbsp;[r&nbsp;&quot;&quot;&nbsp;p&nbsp;prompt] 089&nbsp;&nbsp;&nbsp;&nbsp;(loop&nbsp;[r&nbsp;(read-line)]
</span><br/> </span><br/>
<span class="partial" title="12 out of 13 forms covered"> <span class="partial" title="11 out of 12 forms covered">
088&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(and&nbsp;(seq&nbsp;r) 090&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(and&nbsp;(=&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\(&quot;&nbsp;r))
</span><br/>
<span class="covered" title="6 out of 6 forms covered">
089&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(=&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\(&quot;&nbsp;r))
</span><br/> </span><br/>
<span class="covered" title="5 out of 5 forms covered"> <span class="covered" title="5 out of 5 forms covered">
090&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\)&quot;&nbsp;r))) 091&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\)&quot;&nbsp;r)))
</span><br/> </span><br/>
<span class="covered" title="5 out of 5 forms covered"> <span class="covered" title="5 out of 5 forms covered">
091&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(=&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\[&quot;&nbsp;r)) 092&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(=&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\[&quot;&nbsp;r))
</span><br/> </span><br/>
<span class="covered" title="5 out of 5 forms covered"> <span class="covered" title="5 out of 5 forms covered">
092&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\]&quot;&nbsp;r)))) 093&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\]&quot;&nbsp;r))))
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
093&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r 094&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="not-covered" title="0 out of 1 forms covered">
094&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(do 095&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(recur&nbsp;(str&nbsp;r&nbsp;&quot;\n&quot;&nbsp;(read-line))))))
</span><br/>
<span class="covered" title="6 out of 6 forms covered">
095&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(print&nbsp;(str&nbsp;p&nbsp;&quot;&nbsp;&quot;))
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
096&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(flush)
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
097&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(recur&nbsp;(str&nbsp;r&nbsp;&quot;\n&quot;&nbsp;(read-line))&nbsp;&quot;::&quot;)))))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
098&nbsp;&nbsp; 096&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
099&nbsp;&nbsp;(defn&nbsp;read-from-console 097&nbsp;&nbsp;(defn&nbsp;READ
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
100&nbsp;&nbsp;&nbsp;&nbsp;&quot;Attempt&nbsp;to&nbsp;read&nbsp;a&nbsp;complete&nbsp;lisp&nbsp;expression&nbsp;from&nbsp;the&nbsp;console. 098&nbsp;&nbsp;&nbsp;&nbsp;&quot;An&nbsp;implementation&nbsp;of&nbsp;a&nbsp;Lisp&nbsp;reader&nbsp;sufficient&nbsp;for&nbsp;bootstrapping;&nbsp;not&nbsp;necessarily
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 099&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;final&nbsp;Lisp&nbsp;reader.&nbsp;`input`&nbsp;should&nbsp;be&nbsp;either&nbsp;a&nbsp;string&nbsp;representation&nbsp;of&nbsp;a&nbsp;LISP
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
102&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;There&#x27;s&nbsp;a&nbsp;major&nbsp;problem&nbsp;here&nbsp;that&nbsp;the&nbsp;read-chars&nbsp;reader&nbsp;messes&nbsp;up&nbsp;testing. 100&nbsp;&nbsp;&nbsp;&nbsp;expression,&nbsp;or&nbsp;else&nbsp;an&nbsp;input&nbsp;stream.&nbsp;A&nbsp;single&nbsp;form&nbsp;will&nbsp;be&nbsp;read.&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
103&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;We&nbsp;need&nbsp;to&nbsp;be&nbsp;able&nbsp;to&nbsp;disable&nbsp;it&nbsp;while&nbsp;testing!&quot; 101&nbsp;&nbsp;&nbsp;&nbsp;([]
</span><br/>
<span class="not-covered" title="0 out of 4 forms covered">
102&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(gsp&nbsp;(read-from-console)))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
104&nbsp;&nbsp;&nbsp;&nbsp;[prompt] 103&nbsp;&nbsp;&nbsp;&nbsp;([input]
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
105&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(:testing&nbsp;*options*)
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(dummy-read-chars&nbsp;prompt)
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
107&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(read-chars&nbsp;prompt)))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
108&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
109&nbsp;&nbsp;(defn&nbsp;READ
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
110&nbsp;&nbsp;&nbsp;&nbsp;&quot;An&nbsp;implementation&nbsp;of&nbsp;a&nbsp;Lisp&nbsp;reader&nbsp;sufficient&nbsp;for&nbsp;bootstrapping;&nbsp;not&nbsp;necessarily
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
111&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;final&nbsp;Lisp&nbsp;reader.&nbsp;`input`&nbsp;should&nbsp;be&nbsp;either&nbsp;a&nbsp;string&nbsp;representation&nbsp;of&nbsp;a&nbsp;LISP
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
112&nbsp;&nbsp;&nbsp;&nbsp;expression,&nbsp;or&nbsp;else&nbsp;an&nbsp;input&nbsp;stream.&nbsp;A&nbsp;single&nbsp;form&nbsp;will&nbsp;be&nbsp;read.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
113&nbsp;&nbsp;&nbsp;&nbsp;([]
</span><br/>
<span class="not-covered" title="0 out of 7 forms covered">
114&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(gsp&nbsp;(read-from-console&nbsp;(:prompt&nbsp;*options*))))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
115&nbsp;&nbsp;&nbsp;&nbsp;([input]
</span><br/> </span><br/>
<span class="partial" title="2 out of 4 forms covered"> <span class="partial" title="2 out of 4 forms covered">
116&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cond 104&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cond
</span><br/> </span><br/>
<span class="partial" title="3 out of 5 forms covered"> <span class="partial" title="3 out of 5 forms covered">
117&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(empty?&nbsp;input)&nbsp;(READ) 105&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(empty?&nbsp;input)&nbsp;(READ)
</span><br/> </span><br/>
<span class="covered" title="6 out of 6 forms covered"> <span class="covered" title="6 out of 6 forms covered">
118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(string?&nbsp;input)&nbsp;(gsp&nbsp;input) 106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(string?&nbsp;input)&nbsp;(gsp&nbsp;input)
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 9 forms covered"> <span class="not-covered" title="0 out of 9 forms covered">
119&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(instance?&nbsp;InputStream&nbsp;input)&nbsp;(READ&nbsp;(slurp&nbsp;input)) 107&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(instance?&nbsp;InputStream&nbsp;input)&nbsp;(READ&nbsp;(slurp&nbsp;input))
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 5 forms covered"> <span class="not-covered" title="0 out of 5 forms covered">
120&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:else&nbsp;&nbsp;&nbsp;&nbsp;(throw&nbsp;(ex-info&nbsp;&quot;READ:&nbsp;`input`&nbsp;should&nbsp;be&nbsp;a&nbsp;string&nbsp;or&nbsp;an&nbsp;input&nbsp;stream&quot;&nbsp;{}))))) 108&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:else&nbsp;&nbsp;&nbsp;&nbsp;(throw&nbsp;(ex-info&nbsp;&quot;READ:&nbsp;`input`&nbsp;should&nbsp;be&nbsp;a&nbsp;string&nbsp;or&nbsp;an&nbsp;input&nbsp;stream&quot;&nbsp;{})))))
</span><br/> </span><br/>
</body> </body>
</html> </html>

View file

@ -71,259 +71,163 @@
022&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;7931988&#x2F;how-to-manipulate-control-characters&quot; 022&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;7931988&#x2F;how-to-manipulate-control-characters&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
023&nbsp;&nbsp;&nbsp;&nbsp;(:require&nbsp;[beowulf.oblist&nbsp;:refer&nbsp;[*options*&nbsp;oblist]]) 023&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;(:import&nbsp;[org.jline.reader&nbsp;LineReader&nbsp;LineReaderBuilder]
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
024&nbsp;&nbsp;&nbsp;&nbsp;(:import&nbsp;[org.jline.reader.impl.completer&nbsp;StringsCompleter] 024&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[org.jline.terminal&nbsp;TerminalBuilder])
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
025&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[org.jline.reader.impl&nbsp;DefaultParser&nbsp;DefaultParser$Bracket] 025&nbsp;&nbsp;&nbsp;&nbsp;)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
026&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[org.jline.reader&nbsp;LineReaderBuilder]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
027&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[org.jline.terminal&nbsp;TerminalBuilder]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
028&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[org.jline.widget&nbsp;AutopairWidgets&nbsp;AutosuggestionWidgets]))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
029&nbsp;&nbsp; 026&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
030&nbsp;&nbsp;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 027&nbsp;&nbsp;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
031&nbsp;&nbsp;;;; 028&nbsp;&nbsp;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
032&nbsp;&nbsp;;;;&nbsp;Copyright&nbsp;(C)&nbsp;2022-2023&nbsp;Simon&nbsp;Brooke 029&nbsp;&nbsp;;;;&nbsp;Copyright&nbsp;(C)&nbsp;2022-2023&nbsp;Simon&nbsp;Brooke
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
033&nbsp;&nbsp;;;; 030&nbsp;&nbsp;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
034&nbsp;&nbsp;;;;&nbsp;This&nbsp;program&nbsp;is&nbsp;free&nbsp;software;&nbsp;you&nbsp;can&nbsp;redistribute&nbsp;it&nbsp;and&#x2F;or 031&nbsp;&nbsp;;;;&nbsp;This&nbsp;program&nbsp;is&nbsp;free&nbsp;software;&nbsp;you&nbsp;can&nbsp;redistribute&nbsp;it&nbsp;and&#x2F;or
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
035&nbsp;&nbsp;;;;&nbsp;modify&nbsp;it&nbsp;under&nbsp;the&nbsp;terms&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License 032&nbsp;&nbsp;;;;&nbsp;modify&nbsp;it&nbsp;under&nbsp;the&nbsp;terms&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
036&nbsp;&nbsp;;;;&nbsp;as&nbsp;published&nbsp;by&nbsp;the&nbsp;Free&nbsp;Software&nbsp;Foundation;&nbsp;either&nbsp;version&nbsp;2 033&nbsp;&nbsp;;;;&nbsp;as&nbsp;published&nbsp;by&nbsp;the&nbsp;Free&nbsp;Software&nbsp;Foundation;&nbsp;either&nbsp;version&nbsp;2
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
037&nbsp;&nbsp;;;;&nbsp;of&nbsp;the&nbsp;License,&nbsp;or&nbsp;(at&nbsp;your&nbsp;option)&nbsp;any&nbsp;later&nbsp;version. 034&nbsp;&nbsp;;;;&nbsp;of&nbsp;the&nbsp;License,&nbsp;or&nbsp;(at&nbsp;your&nbsp;option)&nbsp;any&nbsp;later&nbsp;version.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
038&nbsp;&nbsp;;;;&nbsp; 035&nbsp;&nbsp;;;;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
039&nbsp;&nbsp;;;;&nbsp;This&nbsp;program&nbsp;is&nbsp;distributed&nbsp;in&nbsp;the&nbsp;hope&nbsp;that&nbsp;it&nbsp;will&nbsp;be&nbsp;useful, 036&nbsp;&nbsp;;;;&nbsp;This&nbsp;program&nbsp;is&nbsp;distributed&nbsp;in&nbsp;the&nbsp;hope&nbsp;that&nbsp;it&nbsp;will&nbsp;be&nbsp;useful,
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
040&nbsp;&nbsp;;;;&nbsp;but&nbsp;WITHOUT&nbsp;ANY&nbsp;WARRANTY;&nbsp;without&nbsp;even&nbsp;the&nbsp;implied&nbsp;warranty&nbsp;of 037&nbsp;&nbsp;;;;&nbsp;but&nbsp;WITHOUT&nbsp;ANY&nbsp;WARRANTY;&nbsp;without&nbsp;even&nbsp;the&nbsp;implied&nbsp;warranty&nbsp;of
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
041&nbsp;&nbsp;;;;&nbsp;MERCHANTABILITY&nbsp;or&nbsp;FITNESS&nbsp;FOR&nbsp;A&nbsp;PARTICULAR&nbsp;PURPOSE.&nbsp;&nbsp;See&nbsp;the 038&nbsp;&nbsp;;;;&nbsp;MERCHANTABILITY&nbsp;or&nbsp;FITNESS&nbsp;FOR&nbsp;A&nbsp;PARTICULAR&nbsp;PURPOSE.&nbsp;&nbsp;See&nbsp;the
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
042&nbsp;&nbsp;;;;&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License&nbsp;for&nbsp;more&nbsp;details. 039&nbsp;&nbsp;;;;&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License&nbsp;for&nbsp;more&nbsp;details.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
043&nbsp;&nbsp;;;;&nbsp; 040&nbsp;&nbsp;;;;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
044&nbsp;&nbsp;;;;&nbsp;You&nbsp;should&nbsp;have&nbsp;received&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License 041&nbsp;&nbsp;;;;&nbsp;You&nbsp;should&nbsp;have&nbsp;received&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
045&nbsp;&nbsp;;;;&nbsp;along&nbsp;with&nbsp;this&nbsp;program;&nbsp;if&nbsp;not,&nbsp;write&nbsp;to&nbsp;the&nbsp;Free&nbsp;Software 042&nbsp;&nbsp;;;;&nbsp;along&nbsp;with&nbsp;this&nbsp;program;&nbsp;if&nbsp;not,&nbsp;write&nbsp;to&nbsp;the&nbsp;Free&nbsp;Software
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
046&nbsp;&nbsp;;;;&nbsp;Foundation,&nbsp;Inc.,&nbsp;51&nbsp;Franklin&nbsp;Street,&nbsp;Fifth&nbsp;Floor,&nbsp;Boston,&nbsp;MA&nbsp;&nbsp;02110-1301,&nbsp;USA. 043&nbsp;&nbsp;;;;&nbsp;Foundation,&nbsp;Inc.,&nbsp;51&nbsp;Franklin&nbsp;Street,&nbsp;Fifth&nbsp;Floor,&nbsp;Boston,&nbsp;MA&nbsp;&nbsp;02110-1301,&nbsp;USA.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
047&nbsp;&nbsp;;;; 044&nbsp;&nbsp;;;;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
048&nbsp;&nbsp;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 045&nbsp;&nbsp;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
049&nbsp;&nbsp; 046&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
050&nbsp;&nbsp;;;&nbsp;It&nbsp;looks&nbsp;from&nbsp;the&nbsp;example&nbsp;given&nbsp;[here](https:&#x2F;&#x2F;github.com&#x2F;jline&#x2F;jline3&#x2F;blob&#x2F;master&#x2F;demo&#x2F;src&#x2F;main&#x2F;java&#x2F;org&#x2F;jline&#x2F;demo&#x2F;Repl.java) 047&nbsp;&nbsp;;;&nbsp;It&nbsp;looks&nbsp;from&nbsp;the&nbsp;example&nbsp;given&nbsp;[here](https:&#x2F;&#x2F;github.com&#x2F;jline&#x2F;jline3&#x2F;blob&#x2F;master&#x2F;demo&#x2F;src&#x2F;main&#x2F;java&#x2F;org&#x2F;jline&#x2F;demo&#x2F;Repl.java)
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
051&nbsp;&nbsp;;;&nbsp;as&nbsp;though&nbsp;JLine&nbsp;could&nbsp;be&nbsp;used&nbsp;to&nbsp;build&nbsp;a&nbsp;perfect&nbsp;line-reader&nbsp;for&nbsp;Beowulf;&nbsp;but&nbsp;it&nbsp;also 048&nbsp;&nbsp;;;&nbsp;as&nbsp;though&nbsp;JLine&nbsp;could&nbsp;be&nbsp;used&nbsp;to&nbsp;build&nbsp;a&nbsp;perfect&nbsp;line-reader&nbsp;for&nbsp;Beowulf;&nbsp;but&nbsp;it&nbsp;also
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
052&nbsp;&nbsp;;;&nbsp;looks&nbsp;as&nbsp;though&nbsp;you&#x27;d&nbsp;need&nbsp;a&nbsp;DPhil&nbsp;in&nbsp;JLine&nbsp;to&nbsp;write&nbsp;it,&nbsp;and&nbsp;I&nbsp;don&#x27;t&nbsp;have 049&nbsp;&nbsp;;;&nbsp;looks&nbsp;as&nbsp;though&nbsp;you&#x27;d&nbsp;need&nbsp;a&nbsp;DPhil&nbsp;in&nbsp;JLine&nbsp;to&nbsp;write&nbsp;it,&nbsp;and&nbsp;I&nbsp;don&#x27;t&nbsp;have
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
053&nbsp;&nbsp;;;&nbsp;the&nbsp;time. 050&nbsp;&nbsp;;;&nbsp;the&nbsp;time.
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
054&nbsp;&nbsp; 051&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
055&nbsp;&nbsp;(defn&nbsp;build-completer
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
056&nbsp;&nbsp;&nbsp;&nbsp;&quot;Build&nbsp;a&nbsp;completer&nbsp;which&nbsp;takes&nbsp;tokens&nbsp;from&nbsp;the&nbsp;oblist. 052&nbsp;&nbsp;;;&nbsp;(def&nbsp;get-reader
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
057&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 053&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&quot;Return&nbsp;a&nbsp;reader,&nbsp;first&nbsp;constructing&nbsp;it&nbsp;if&nbsp;necessary.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
058&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;This&nbsp;is&nbsp;sort-of&nbsp;working,&nbsp;in&nbsp;as&nbsp;much&nbsp;as&nbsp;hitting&nbsp;&lt;TAB&gt;&nbsp;on&nbsp;a&nbsp;blank&nbsp;line&nbsp;will&nbsp; 054&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
059&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;show&nbsp;a&nbsp;table&nbsp;of&nbsp;values&nbsp;from&nbsp;the&nbsp;oblist,&nbsp;but&nbsp;hitting&nbsp;&lt;TAB&gt;&nbsp;after&nbsp;you&#x27;ve&nbsp; 055&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;**NOTE&nbsp;THAT**&nbsp;this&nbsp;is&nbsp;not&nbsp;settled&nbsp;API.&nbsp;The&nbsp;existence&nbsp;and&nbsp;call&nbsp;signature&nbsp;of
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
060&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;started&nbsp;input&nbsp;does&nbsp;not&nbsp;show&nbsp;potential&nbsp;completions&nbsp;for&nbsp;tokens&nbsp;you&#x27;ve&nbsp;started.&quot; 056&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;this&nbsp;function&nbsp;is&nbsp;not&nbsp;guaranteed&nbsp;in&nbsp;future&nbsp;versions.&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
061&nbsp;&nbsp;&nbsp;&nbsp;[] 057&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;(memoize&nbsp;(fn&nbsp;[]
</span><br/> </span><br/>
<span class="not-covered" title="0 out of 12 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
062&nbsp;&nbsp;&nbsp;&nbsp;(StringsCompleter.&nbsp;(map&nbsp;#(str&nbsp;(first&nbsp;%))&nbsp;@oblist))) 058&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;(let&nbsp;[term&nbsp;(.build&nbsp;(.system&nbsp;(TerminalBuilder&#x2F;builder)&nbsp;true))]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
059&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.build&nbsp;(.terminal&nbsp;(LineReaderBuilder&#x2F;builder)&nbsp;term))))))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
063&nbsp;&nbsp; 060&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
064&nbsp;&nbsp;;;&nbsp;This&nbsp;breaks;&nbsp;it&nbsp;is&nbsp;not&nbsp;correctly&nbsp;resolving&nbsp;the&nbsp;Enum,&nbsp;although&nbsp;I&nbsp;can&#x27;t&nbsp;work&nbsp;out 061&nbsp;&nbsp;;;&nbsp;(defn&nbsp;read-chars
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
065&nbsp;&nbsp;;;&nbsp;why&nbsp;not. 062&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&quot;A&nbsp;drop-in&nbsp;replacement&nbsp;for&nbsp;`clojure.core&#x2F;read-line`,&nbsp;except&nbsp;that&nbsp;line&nbsp;editing
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
066&nbsp;&nbsp;;;&nbsp;(defn&nbsp;build-parser 063&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;history&nbsp;should&nbsp;be&nbsp;enabled.
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
067&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;[] 064&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
068&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;(println&nbsp;&quot;Building&nbsp;parser&quot;) 065&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;**NOTE&nbsp;THAT**&nbsp;this&nbsp;does&nbsp;not&nbsp;work&nbsp;yet,&nbsp;but&nbsp;it&nbsp;is&nbsp;in&nbsp;the&nbsp;API&nbsp;because&nbsp;I&nbsp;hope&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
069&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;(let&nbsp;[parser&nbsp;(DefaultParser.)] 066&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;that&nbsp;it&nbsp;will&nbsp;work&nbsp;later!&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
070&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(doall 067&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;[]&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
071&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.setEofOnUnclosedBracket&nbsp; 068&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[eddie&nbsp;(get-reader)]
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
072&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parser&nbsp;DefaultParser$Bracket&#x2F;ROUND)))) 069&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(loop&nbsp;[s&nbsp;(.readLine&nbsp;eddie)]
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
073&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
074&nbsp;&nbsp;(def&nbsp;get-reader
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
075&nbsp;&nbsp;&nbsp;&nbsp;&quot;Return&nbsp;a&nbsp;reader,&nbsp;first&nbsp;constructing&nbsp;it&nbsp;if&nbsp;necessary. 070&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(and&nbsp;(=&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\(&quot;&nbsp;s))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
076&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 071&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\)&quot;&nbsp;s)))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
077&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**NOTE&nbsp;THAT**&nbsp;this&nbsp;is&nbsp;not&nbsp;settled&nbsp;API.&nbsp;The&nbsp;existence&nbsp;and&nbsp;call&nbsp;signature&nbsp;of 072&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(=&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\[]&quot;&nbsp;s))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
078&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this&nbsp;function&nbsp;is&nbsp;not&nbsp;guaranteed&nbsp;in&nbsp;future&nbsp;versions.&quot; 073&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\]&quot;&nbsp;s))))
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
079&nbsp;&nbsp;&nbsp;&nbsp;(memoize&nbsp;(fn&nbsp;[]
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
080&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[term&nbsp;(.build&nbsp;(.system&nbsp;(TerminalBuilder&#x2F;builder)&nbsp;true))
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
081&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reader&nbsp;(-&gt;&nbsp;(LineReaderBuilder&#x2F;builder)
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
082&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.terminal&nbsp;&nbsp;term)
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
083&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.completer&nbsp;&nbsp;(build-completer))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
084&nbsp;&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#(.parser&nbsp;%&nbsp;(build-parser)) 074&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
085&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.build)) 075&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(recur&nbsp;(str&nbsp;s&nbsp;&quot;&nbsp;&quot;&nbsp;(.readLine&nbsp;eddie)))))))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
086&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;apw&nbsp;(AutopairWidgets.&nbsp;reader&nbsp;false)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
087&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;asw&nbsp;(AutosuggestionWidgets.&nbsp;reader)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
088&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
089&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;(.enable&nbsp;apw)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
090&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;(.enable&nbsp;asw)
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
091&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reader))))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
092&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
093&nbsp;&nbsp;(defn&nbsp;read-chars
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
094&nbsp;&nbsp;&nbsp;&nbsp;&quot;A&nbsp;drop-in&nbsp;replacement&nbsp;for&nbsp;`clojure.core&#x2F;read-line`,&nbsp;except&nbsp;that&nbsp;line&nbsp;editing
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
095&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;history&nbsp;should&nbsp;be&nbsp;enabled.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
096&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
097&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**NOTE&nbsp;THAT**&nbsp;this&nbsp;does&nbsp;not&nbsp;fully&nbsp;work&nbsp;yet,&nbsp;but&nbsp;it&nbsp;is&nbsp;in&nbsp;the&nbsp;API&nbsp;because&nbsp;I&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
098&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hope&nbsp;that&nbsp;it&nbsp;will&nbsp;work&nbsp;later!&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
099&nbsp;&nbsp;&nbsp;&nbsp;[prompt]
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
100&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[eddie&nbsp;(get-reader)]
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(loop&nbsp;[s&nbsp;(.readLine&nbsp;eddie&nbsp;(str&nbsp;prompt&nbsp;&quot;&nbsp;&quot;))]
</span><br/>
<span class="not-covered" title="0 out of 12 forms covered">
102&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(and&nbsp;(=&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\(&quot;&nbsp;s))
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
103&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\)&quot;&nbsp;s)))
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
104&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(=&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\[]&quot;&nbsp;s))
</span><br/>
<span class="not-covered" title="0 out of 5 forms covered">
105&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(count&nbsp;(re-seq&nbsp;#&quot;\]&quot;&nbsp;s))))
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s
</span><br/>
<span class="not-covered" title="0 out of 1 forms covered">
107&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(recur&nbsp;(str&nbsp;s&nbsp;&quot;&nbsp;&quot;&nbsp;(.readLine&nbsp;eddie&nbsp;&quot;::&nbsp;&quot;)))))))
</span><br/> </span><br/>
</body> </body>
</html> </html>

View file

@ -16,11 +16,11 @@
</tr></thead> </tr></thead>
<tr> <tr>
<td><a href="beowulf/bootstrap.clj.html">beowulf.bootstrap</a></td><td class="with-bar"><div class="covered" <td><a href="beowulf/bootstrap.clj.html">beowulf.bootstrap</a></td><td class="with-bar"><div class="covered"
style="width:64.03688524590164%; style="width:63.9344262295082%;
float:left;"> 625 </div><div class="not-covered" float:left;"> 624 </div><div class="not-covered"
style="width:35.96311475409836%; style="width:36.0655737704918%;
float:left;"> 351 </div></td> float:left;"> 352 </div></td>
<td class="with-number">64.04 %</td> <td class="with-number">63.93 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:59.48275862068966%; style="width:59.48275862068966%;
float:left;"> 138 </div><div class="partial" float:left;"> 138 </div><div class="partial"
@ -33,54 +33,54 @@
</tr> </tr>
<tr> <tr>
<td><a href="beowulf/cons_cell.clj.html">beowulf.cons-cell</a></td><td class="with-bar"><div class="covered" <td><a href="beowulf/cons_cell.clj.html">beowulf.cons-cell</a></td><td class="with-bar"><div class="covered"
style="width:76.0914760914761%; style="width:72.34927234927235%;
float:left;"> 366 </div><div class="not-covered" float:left;"> 348 </div><div class="not-covered"
style="width:23.908523908523907%; style="width:27.65072765072765%;
float:left;"> 115 </div></td> float:left;"> 133 </div></td>
<td class="with-number">76.09 %</td> <td class="with-number">72.35 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:78.62068965517241%; style="width:75.17241379310344%;
float:left;"> 114 </div><div class="partial" float:left;"> 109 </div><div class="partial"
style="width:6.206896551724138%; style="width:6.206896551724138%;
float:left;"> 9 </div><div class="not-covered" float:left;"> 9 </div><div class="not-covered"
style="width:15.172413793103448%; style="width:18.620689655172413%;
float:left;"> 22 </div></td> float:left;"> 27 </div></td>
<td class="with-number">84.83 %</td> <td class="with-number">81.38 %</td>
<td class="with-number">274</td><td class="with-number">23</td><td class="with-number">145</td> <td class="with-number">274</td><td class="with-number">23</td><td class="with-number">145</td>
</tr> </tr>
<tr> <tr>
<td><a href="beowulf/core.clj.html">beowulf.core</a></td><td class="with-bar"><div class="covered" <td><a href="beowulf/core.clj.html">beowulf.core</a></td><td class="with-bar"><div class="covered"
style="width:73.94366197183099%; style="width:69.47368421052632%;
float:left;"> 210 </div><div class="not-covered" float:left;"> 198 </div><div class="not-covered"
style="width:26.056338028169016%; style="width:30.526315789473685%;
float:left;"> 74 </div></td> float:left;"> 87 </div></td>
<td class="with-number">73.94 %</td> <td class="with-number">69.47 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:78.26086956521739%; style="width:72.46376811594203%;
float:left;"> 54 </div><div class="partial" float:left;"> 50 </div><div class="partial"
style="width:2.898550724637681%; style="width:5.797101449275362%;
float:left;"> 2 </div><div class="not-covered" float:left;"> 4 </div><div class="not-covered"
style="width:18.840579710144926%; style="width:21.73913043478261%;
float:left;"> 13 </div></td> float:left;"> 15 </div></td>
<td class="with-number">81.16 %</td> <td class="with-number">78.26 %</td>
<td class="with-number">132</td><td class="with-number">6</td><td class="with-number">69</td> <td class="with-number">132</td><td class="with-number">6</td><td class="with-number">69</td>
</tr> </tr>
<tr> <tr>
<td><a href="beowulf/host.clj.html">beowulf.host</a></td><td class="with-bar"><div class="covered" <td><a href="beowulf/host.clj.html">beowulf.host</a></td><td class="with-bar"><div class="covered"
style="width:56.44047135310849%; style="width:42.77384423157018%;
float:left;"> 1389 </div><div class="not-covered" float:left;"> 1027 </div><div class="not-covered"
style="width:43.55952864689151%; style="width:57.22615576842982%;
float:left;"> 1072 </div></td> float:left;"> 1374 </div></td>
<td class="with-number">56.44 %</td> <td class="with-number">42.77 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:75.37878787878788%; style="width:53.72549019607843%;
float:left;"> 199 </div><div class="partial" float:left;"> 137 </div><div class="partial"
style="width:12.121212121212121%; style="width:14.509803921568627%;
float:left;"> 32 </div><div class="not-covered" float:left;"> 37 </div><div class="not-covered"
style="width:12.5%; style="width:31.764705882352942%;
float:left;"> 33 </div></td> float:left;"> 81 </div></td>
<td class="with-number">87.50 %</td> <td class="with-number">68.24 %</td>
<td class="with-number">589</td><td class="with-number">67</td><td class="with-number">264</td> <td class="with-number">571</td><td class="with-number">66</td><td class="with-number">255</td>
</tr> </tr>
<tr> <tr>
<td><a href="beowulf/interop.clj.html">beowulf.interop</a></td><td class="with-bar"><div class="covered" <td><a href="beowulf/interop.clj.html">beowulf.interop</a></td><td class="with-bar"><div class="covered"
@ -107,14 +107,14 @@
float:left;"> 181 </div></td> float:left;"> 181 </div></td>
<td class="with-number">43.96 %</td> <td class="with-number">43.96 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:45.833333333333336%; style="width:46.478873239436616%;
float:left;"> 33 </div><div class="partial" float:left;"> 33 </div><div class="partial"
style="width:8.333333333333334%; style="width:8.450704225352112%;
float:left;"> 6 </div><div class="not-covered" float:left;"> 6 </div><div class="not-covered"
style="width:45.833333333333336%; style="width:45.070422535211264%;
float:left;"> 33 </div></td> float:left;"> 32 </div></td>
<td class="with-number">54.17 %</td> <td class="with-number">54.93 %</td>
<td class="with-number">171</td><td class="with-number">12</td><td class="with-number">72</td> <td class="with-number">171</td><td class="with-number">12</td><td class="with-number">71</td>
</tr> </tr>
<tr> <tr>
<td><a href="beowulf/manual.clj.html">beowulf.manual</a></td><td class="with-bar"><div class="covered" <td><a href="beowulf/manual.clj.html">beowulf.manual</a></td><td class="with-bar"><div class="covered"
@ -134,7 +134,7 @@
<tr> <tr>
<td><a href="beowulf/oblist.clj.html">beowulf.oblist</a></td><td class="with-bar"><div class="covered" <td><a href="beowulf/oblist.clj.html">beowulf.oblist</a></td><td class="with-bar"><div class="covered"
style="width:100.0%; style="width:100.0%;
float:left;"> 11 </div></td> float:left;"> 9 </div></td>
<td class="with-number">100.00 %</td> <td class="with-number">100.00 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:100.0%; style="width:100.0%;
@ -144,35 +144,31 @@
</tr> </tr>
<tr> <tr>
<td><a href="beowulf/read.clj.html">beowulf.read</a></td><td class="with-bar"><div class="covered" <td><a href="beowulf/read.clj.html">beowulf.read</a></td><td class="with-bar"><div class="covered"
style="width:54.36893203883495%; style="width:49.43181818181818%;
float:left;"> 112 </div><div class="not-covered" float:left;"> 87 </div><div class="not-covered"
style="width:45.63106796116505%; style="width:50.56818181818182%;
float:left;"> 94 </div></td> float:left;"> 89 </div></td>
<td class="with-number">54.37 %</td> <td class="with-number">49.43 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:61.702127659574465%; style="width:53.84615384615385%;
float:left;"> 29 </div><div class="partial" float:left;"> 21 </div><div class="partial"
style="width:6.382978723404255%; style="width:7.6923076923076925%;
float:left;"> 3 </div><div class="not-covered" float:left;"> 3 </div><div class="not-covered"
style="width:31.914893617021278%; style="width:38.46153846153846%;
float:left;"> 15 </div></td> float:left;"> 15 </div></td>
<td class="with-number">68.09 %</td> <td class="with-number">61.54 %</td>
<td class="with-number">120</td><td class="with-number">10</td><td class="with-number">47</td> <td class="with-number">108</td><td class="with-number">9</td><td class="with-number">39</td>
</tr> </tr>
<tr> <tr>
<td><a href="beowulf/reader/char_reader.clj.html">beowulf.reader.char-reader</a></td><td class="with-bar"><div class="covered" <td><a href="beowulf/reader/char_reader.clj.html">beowulf.reader.char-reader</a></td><td class="with-bar"><div class="covered"
style="width:10.0%; style="width:100.0%;
float:left;"> 7 </div><div class="not-covered" float:left;"> 1 </div></td>
style="width:90.0%; <td class="with-number">100.00 %</td>
float:left;"> 63 </div></td>
<td class="with-number">10.00 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:26.31578947368421%; style="width:100.0%;
float:left;"> 5 </div><div class="not-covered" float:left;"> 1 </div></td>
style="width:73.6842105263158%; <td class="with-number">100.00 %</td>
float:left;"> 14 </div></td> <td class="with-number">75</td><td class="with-number">4</td><td class="with-number">1</td>
<td class="with-number">26.32 %</td>
<td class="with-number">107</td><td class="with-number">6</td><td class="with-number">19</td>
</tr> </tr>
<tr> <tr>
<td><a href="beowulf/reader/generate.clj.html">beowulf.reader.generate</a></td><td class="with-bar"><div class="covered" <td><a href="beowulf/reader/generate.clj.html">beowulf.reader.generate</a></td><td class="with-bar"><div class="covered"
@ -236,9 +232,9 @@
</tr> </tr>
<tr><td>Totals:</td> <tr><td>Totals:</td>
<td class="with-bar"></td> <td class="with-bar"></td>
<td class="with-number">68.60 %</td> <td class="with-number">64.63 %</td>
<td class="with-bar"></td> <td class="with-bar"></td>
<td class="with-number">77.76 %</td> <td class="with-number">74.41 %</td>
</tr> </tr>
</table> </table>
</body> </body>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
<!DOCTYPE html PUBLIC "" <!DOCTYPE html PUBLIC ""
""> "">
<html><head><meta charset="UTF-8" /><title>Further Reading</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><link rel="icon" type="image/x-icon" href="../img/beowulf_logo_favicon.png" /></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Beowulf</span> <span class="project-version">0.3.1-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 current"><a href="further_reading.html"><div class="inner"><span>Further Reading</span></div></a></li><li class="depth-1 "><a href="intro.html"><div class="inner"><span>beowulf</span></div></a></li><li class="depth-1 "><a href="mexpr.html"><div class="inner"><span>Interpreting M-Expressions</span></div></a></li><li class="depth-1 "><a href="values.html"><div class="inner"><span>The properties of the system, and their values</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>beowulf</span></div></div></li><li class="depth-2 branch"><a href="beowulf.bootstrap.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>bootstrap</span></div></a></li><li class="depth-2 branch"><a href="beowulf.cons-cell.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>cons-cell</span></div></a></li><li class="depth-2 branch"><a href="beowulf.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2 branch"><a href="beowulf.gendoc.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>gendoc</span></div></a></li><li class="depth-2 branch"><a href="beowulf.host.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>host</span></div></a></li><li class="depth-2 branch"><a href="beowulf.interop.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>interop</span></div></a></li><li class="depth-2 branch"><a href="beowulf.io.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>io</span></div></a></li><li class="depth-2 branch"><a href="beowulf.manual.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>manual</span></div></a></li><li class="depth-2 branch"><a href="beowulf.oblist.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>oblist</span></div></a></li><li class="depth-2 branch"><a href="beowulf.read.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>read</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>reader</span></div></div></li><li class="depth-3 branch"><a href="beowulf.reader.char-reader.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>char-reader</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.generate.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>generate</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.macros.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>macros</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.parser.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>parser</span></div></a></li><li class="depth-3"><a href="beowulf.reader.simplify.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simplify</span></div></a></li></ul></div><div class="document" id="content"><div class="doc"><div class="markdown"><h1><a href="#further-reading" id="further-reading"></a>Further Reading</h1> <html><head><meta charset="UTF-8" /><title>Further Reading</title><link rel="icon" type="image/x-icon" href="../img/beowulf_logo_favicon.png" /><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Beowulf</span> <span class="project-version">0.3.0</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 current"><a href="further_reading.html"><div class="inner"><span>Further Reading</span></div></a></li><li class="depth-1 "><a href="intro.html"><div class="inner"><span>beowulf</span></div></a></li><li class="depth-1 "><a href="mexpr.html"><div class="inner"><span>Interpreting M-Expressions</span></div></a></li><li class="depth-1 "><a href="values.html"><div class="inner"><span>The properties of the system, and their values</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>beowulf</span></div></div></li><li class="depth-2 branch"><a href="beowulf.bootstrap.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>bootstrap</span></div></a></li><li class="depth-2 branch"><a href="beowulf.cons-cell.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>cons-cell</span></div></a></li><li class="depth-2 branch"><a href="beowulf.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2 branch"><a href="beowulf.gendoc.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>gendoc</span></div></a></li><li class="depth-2 branch"><a href="beowulf.host.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>host</span></div></a></li><li class="depth-2 branch"><a href="beowulf.interop.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>interop</span></div></a></li><li class="depth-2 branch"><a href="beowulf.io.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>io</span></div></a></li><li class="depth-2 branch"><a href="beowulf.manual.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>manual</span></div></a></li><li class="depth-2 branch"><a href="beowulf.oblist.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>oblist</span></div></a></li><li class="depth-2 branch"><a href="beowulf.read.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>read</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>reader</span></div></div></li><li class="depth-3 branch"><a href="beowulf.reader.char-reader.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>char-reader</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.generate.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>generate</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.macros.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>macros</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.parser.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>parser</span></div></a></li><li class="depth-3"><a href="beowulf.reader.simplify.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simplify</span></div></a></li></ul></div><div class="document" id="content"><div class="doc"><div class="markdown"><h1><a href="#further-reading" name="further-reading"></a>Further Reading</h1>
<ol> <ol>
<li><a href="http://bitsavers.org/pdf/mit/computer_center/Coding_for_the_MIT-IBM_704_Computer_Oct57.pdf">CODING for the MIT-IBM 704 COMPUTER, October 1957</a> This paper is not about Lisp. But it is about the particular individual computer on which Lisp was first implemented, and it is written in part by members of the Lisp team. I have found it useful in understanding the software environment in which, and the constraints under which, Lisp was written.</li> <li><a href="http://bitsavers.org/pdf/mit/computer_center/Coding_for_the_MIT-IBM_704_Computer_Oct57.pdf">CODING for the MIT-IBM 704 COMPUTER, October 1957</a> This paper is not about Lisp. But it is about the particular individual computer on which Lisp was first implemented, and it is written in part by members of the Lisp team. I have found it useful in understanding the software environment in which, and the constraints under which, Lisp was written.</li>
<li><a href="https://www.softwarepreservation.org/projects/LISP/MIT/AIM-001.pdf">MIT AI Memo 1, John McCarthy, September 1958</a> This is, as far as I can find, the earliest specification document of the Lisp project.</li> <li><a href="https://www.softwarepreservation.org/projects/LISP/MIT/AIM-001.pdf">MIT AI Memo 1, John McCarthy, September 1958</a> This is, as far as I can find, the earliest specification document of the Lisp project.</li>
@ -8,12 +8,10 @@
<li><a href="https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=81">Lisp 1.5 Programmers Manual, Michael I. Levin, August 1962</a> This book is essential reading: it documents in some detail the first fully realised Lisp language system.</li> <li><a href="https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=81">Lisp 1.5 Programmers Manual, Michael I. Levin, August 1962</a> This book is essential reading: it documents in some detail the first fully realised Lisp language system.</li>
<li><a href="https://dl.acm.org/doi/pdf/10.1145/800055.802047#page=3">Early LISP History (1956 - 1959), Herbert Stoyan, August 1984</a></li> <li><a href="https://dl.acm.org/doi/pdf/10.1145/800055.802047#page=3">Early LISP History (1956 - 1959), Herbert Stoyan, August 1984</a></li>
<li> <li>
<p><a href="http://www.paulgraham.com/rootsoflisp.html">The Roots of Lisp, Paul Graham, 2001</a></p> <p><a href="http://www.paulgraham.com/rootsoflisp.html">The Roots of Lisp, Paul Graham, 2001</a></p></li>
</li> <li>
<li><a href="http://www.paulgraham.com/icad.html">The Revenge of the Nerds, Paul Graham, 2002</a> This is mainly about why to use Lisp as a language for modern commercial software, but has useful insights into where it comes from. <p><a href="http://www.paulgraham.com/icad.html">The Revenge of the Nerds, Paul Graham, 2002</a> This is mainly about why to use Lisp as a language for modern commercial software, but has useful insights into where it comes from.</p>
<blockquote> <blockquote>
<p>So the short explanation of why this 1950s language is not obsolete is that it was not technology but math, and math doesnt get stale.</p> <p>So the short explanation of why this 1950s language is not obsolete is that it was not technology but math, and math doesnt get stale.</p>
</blockquote> </blockquote></li>
</li> </ol></div></div></div></body></html>
</ol>
</div></div></div></body></html>

File diff suppressed because one or more lines are too long

View file

@ -1,10 +1,10 @@
<!DOCTYPE html PUBLIC "" <!DOCTYPE html PUBLIC ""
""> "">
<html><head><meta charset="UTF-8" /><title>beowulf</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><link rel="icon" type="image/x-icon" href="../img/beowulf_logo_favicon.png" /></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Beowulf</span> <span class="project-version">0.3.1-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 "><a href="further_reading.html"><div class="inner"><span>Further Reading</span></div></a></li><li class="depth-1 current"><a href="intro.html"><div class="inner"><span>beowulf</span></div></a></li><li class="depth-1 "><a href="mexpr.html"><div class="inner"><span>Interpreting M-Expressions</span></div></a></li><li class="depth-1 "><a href="values.html"><div class="inner"><span>The properties of the system, and their values</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>beowulf</span></div></div></li><li class="depth-2 branch"><a href="beowulf.bootstrap.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>bootstrap</span></div></a></li><li class="depth-2 branch"><a href="beowulf.cons-cell.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>cons-cell</span></div></a></li><li class="depth-2 branch"><a href="beowulf.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2 branch"><a href="beowulf.gendoc.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>gendoc</span></div></a></li><li class="depth-2 branch"><a href="beowulf.host.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>host</span></div></a></li><li class="depth-2 branch"><a href="beowulf.interop.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>interop</span></div></a></li><li class="depth-2 branch"><a href="beowulf.io.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>io</span></div></a></li><li class="depth-2 branch"><a href="beowulf.manual.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>manual</span></div></a></li><li class="depth-2 branch"><a href="beowulf.oblist.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>oblist</span></div></a></li><li class="depth-2 branch"><a href="beowulf.read.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>read</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>reader</span></div></div></li><li class="depth-3 branch"><a href="beowulf.reader.char-reader.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>char-reader</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.generate.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>generate</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.macros.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>macros</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.parser.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>parser</span></div></a></li><li class="depth-3"><a href="beowulf.reader.simplify.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simplify</span></div></a></li></ul></div><div class="document" id="content"><div class="doc"><div class="markdown"><h1><a href="#beowulf" id="beowulf"></a>beowulf</h1> <html><head><meta charset="UTF-8" /><title>beowulf</title><link rel="icon" type="image/x-icon" href="../img/beowulf_logo_favicon.png" /><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Beowulf</span> <span class="project-version">0.3.0</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 "><a href="further_reading.html"><div class="inner"><span>Further Reading</span></div></a></li><li class="depth-1 current"><a href="intro.html"><div class="inner"><span>beowulf</span></div></a></li><li class="depth-1 "><a href="mexpr.html"><div class="inner"><span>Interpreting M-Expressions</span></div></a></li><li class="depth-1 "><a href="values.html"><div class="inner"><span>The properties of the system, and their values</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>beowulf</span></div></div></li><li class="depth-2 branch"><a href="beowulf.bootstrap.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>bootstrap</span></div></a></li><li class="depth-2 branch"><a href="beowulf.cons-cell.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>cons-cell</span></div></a></li><li class="depth-2 branch"><a href="beowulf.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2 branch"><a href="beowulf.gendoc.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>gendoc</span></div></a></li><li class="depth-2 branch"><a href="beowulf.host.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>host</span></div></a></li><li class="depth-2 branch"><a href="beowulf.interop.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>interop</span></div></a></li><li class="depth-2 branch"><a href="beowulf.io.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>io</span></div></a></li><li class="depth-2 branch"><a href="beowulf.manual.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>manual</span></div></a></li><li class="depth-2 branch"><a href="beowulf.oblist.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>oblist</span></div></a></li><li class="depth-2 branch"><a href="beowulf.read.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>read</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>reader</span></div></div></li><li class="depth-3 branch"><a href="beowulf.reader.char-reader.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>char-reader</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.generate.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>generate</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.macros.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>macros</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.parser.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>parser</span></div></a></li><li class="depth-3"><a href="beowulf.reader.simplify.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simplify</span></div></a></li></ul></div><div class="document" id="content"><div class="doc"><div class="markdown"><h1><a href="#beowulf" name="beowulf"></a>beowulf</h1>
<h2><a href="#þý-liste-cræfte-spræc" id="þý-liste-cræfte-spræc"></a>Þý liste cræfte spræc</h2> <h2><a href="#þý-liste-cræfte-spræc" name="þý-liste-cræfte-spræc"></a>Þý liste cræfte spræc</h2>
<p>LISP 1.5 is to all Lisp dialects as Beowulf is to English literature.</p> <p>LISP 1.5 is to all Lisp dialects as Beowulf is to English literature.</p>
<p><img src="https://simon-brooke.github.io/beowulf/docs/img/beowulf_logo_med.png" alt="Beowulf logo" /></p> <p><img src="https://simon-brooke.github.io/beowulf/docs/img/beowulf_logo_med.png" alt="Beowulf logo" /></p>
<h2><a href="#contents" id="contents"></a>Contents</h2> <h2><a href="#contents" name="contents"></a>Contents</h2>
<ul> <ul>
<li><a href="#what-this-is">What this is</a> <li><a href="#what-this-is">What this is</a>
<ul> <ul>
@ -39,26 +39,26 @@
</li> </li>
<li><a href="#license">License</a></li> <li><a href="#license">License</a></li>
</ul> </ul>
<p><small><i><a href="http://ecotrust-canada.github.io/markdown-toc/">Table of contents generated with markdown-toc</a></i></small></p> <small><i><a href="http://ecotrust-canada.github.io/markdown-toc/">Table of contents generated with markdown-toc</a></i></small>
<h2><a href="#what-this-is" id="what-this-is"></a>What this is</h2> <h2><a href="#what-this-is" name="what-this-is"></a>What this is</h2>
<p>A work-in-progress towards an implementation of Lisp 1.5 in Clojure. The objective is to build a complete and accurate implementation of Lisp 1.5 as described in the manual, with, in so far as is possible, exactly the same bahaviour - except as documented below.</p> <p>A work-in-progress towards an implementation of Lisp 1.5 in Clojure. The objective is to build a complete and accurate implementation of Lisp 1.5 as described in the manual, with, in so far as is possible, exactly the same bahaviour - except as documented below.</p>
<h3><a href="#but-why" id="but-why"></a>BUT WHY?!!?!</h3> <h3><a href="#but-why-" name="but-why-"></a>BUT WHY?!!?!</h3>
<p>Because.</p> <p>Because.</p>
<p>Because Lisp is the only computer language worth learning, and if a thing is worth learning, its worth learning properly; which means going back to the beginning and trying to understand that.</p> <p>Because Lisp is the only computer language worth learning, and if a thing is worth learning, its worth learning properly; which means going back to the beginning and trying to understand that.</p>
<p>Because there is, so far as I know, no working implementation of Lisp 1.5 for modern machines.</p> <p>Because there is, so far as I know, no working implementation of Lisp 1.5 for modern machines.</p>
<p>Because Im barking mad, and this is therapy.</p> <p>Because Im barking mad, and this is therapy.</p>
<h3><a href="#status" id="status"></a>Status</h3> <h3><a href="#status" name="status"></a>Status</h3>
<p>Working Lisp interpreter, but some key features not yet implemented.</p> <p>Working Lisp interpreter, but some key features not yet implemented.</p>
<ul> <ul>
<li><a href="https://simon-brooke.github.io/beowulf/">Project website</a>.</li> <li><a href="https://simon-brooke.github.io/beowulf/">Project website</a>.</li>
<li><a href="https://simon-brooke.github.io/beowulf/docs/codox/index.html">Source code documentation</a>.</li> <li><a href="https://simon-brooke.github.io/beowulf/docs/codox/index.html">Source code documentation</a>.</li>
</ul> </ul>
<h3><a href="#project-target" id="project-target"></a>Project Target</h3> <h3><a href="#project-target" name="project-target"></a>Project Target</h3>
<p>The project target is to be able to run the <a href="https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=52">Wang algorithm for the propositional calculus</a> given in chapter 8 of the <em>Lisp 1.5 Programmers Manual</em>. When that runs, the project is as far as I am concerned feature complete. I may keep tinkering with it after that and Ill certainly accept pull requests which are in the spirit of the project (i.e. making Beowulf more usable, and/or implementing parts of Lisp 1.5 which I have not implemented), but this isnt intended to be a new language for doing real work; its an educational and archaeological project, not serious engineering.</p> <p>The project target is to be able to run the <a href="https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf#page=52">Wang algorithm for the propositional calculus</a> given in chapter 8 of the <em>Lisp 1.5 Programmers Manual</em>. When that runs, the project is as far as I am concerned feature complete. I may keep tinkering with it after that and Ill certainly accept pull requests which are in the spirit of the project (i.e. making Beowulf more usable, and/or implementing parts of Lisp 1.5 which I have not implemented), but this isnt intended to be a new language for doing real work; its an educational and archaeological project, not serious engineering.</p>
<p>Some <code>readline</code>-like functionality would be really useful, but my attempt to integrate <a href="https://github.com/jline/jline3">JLine</a> has not (yet) been successful.</p> <p>Some <code>readline</code>-like functionality would be really useful, but my attempt to integrate <a href="https://github.com/jline/jline3">JLine</a> has not (yet) been successful.</p>
<p>An in-core structure editor would be an extremely nice thing, and I may well implement one.</p> <p>An in-core structure editor would be an extremely nice thing, and I may well implement one.</p>
<p>You are of course welcome to fork the project and do whatever you like with it!</p> <p>You are of course welcome to fork the project and do whatever you like with it!</p>
<h3><a href="#invoking" id="invoking"></a>Invoking</h3> <h3><a href="#invoking" name="invoking"></a>Invoking</h3>
<p>Invoke with</p> <p>Invoke with</p>
<pre><code>java -jar target/uberjar/beowulf-0.3.0-standalone.jar --help <pre><code>java -jar target/uberjar/beowulf-0.3.0-standalone.jar --help
</code></pre> </code></pre>
@ -72,123 +72,717 @@
without extensions. without extensions.
</code></pre> </code></pre>
<p>To end a session, type <code>STOP</code> at the command prompt.</p> <p>To end a session, type <code>STOP</code> at the command prompt.</p>
<h3><a href="#building-and-invoking" id="building-and-invoking"></a>Building and Invoking</h3> <h3><a href="#building-and-invoking" name="building-and-invoking"></a>Building and Invoking</h3>
<p>Build with</p> <p>Build with</p>
<pre><code>lein uberjar <pre><code>lein uberjar
</code></pre> </code></pre>
<h3><a href="#reader-macros" id="reader-macros"></a>Reader macros</h3> <h3><a href="#reader-macros" name="reader-macros"></a>Reader macros</h3>
<p>Currently <code>SETQ</code> and <code>DEFUN</code> are implemented as reader macros, sort of. It would now be possible to reimplement them as <code>FEXPRs</code> and so the reader macro functionality will probably go away.</p> <p>Currently <code>SETQ</code> and <code>DEFUN</code> are implemented as reader macros, sort of. It would now be possible to reimplement them as <code>FEXPRs</code> and so the reader macro functionality will probably go away.</p>
<h3><a href="#functions-and-symbols-implemented" id="functions-and-symbols-implemented"></a>Functions and symbols implemented</h3> <h3><a href="#functions-and-symbols-implemented" name="functions-and-symbols-implemented"></a>Functions and symbols implemented</h3>
<table> <table>
<thead> <thead>
<tr><th> Function </th><th> Type </th><th> Signature </th><th> Implementation </th><th> Documentation </th></tr> <tr>
<th>Function </th>
<th>Type </th>
<th>Signature </th>
<th>Implementation </th>
<th>Documentation </th>
</tr>
</thead> </thead>
<tbody> <tbody>
<tr><td> NIL </td><td> Lisp variable </td><td> ? </td><td> </td><td> see manual pages <a href="#page22">22</a>, <a href="#page69">69</a> </td></tr> <tr>
<tr><td> T </td><td> Lisp variable </td><td> ? </td><td> </td><td> see manual pages <a href="#page22">22</a>, <a href="#page69">69</a> </td></tr> <td>NIL </td>
<tr><td> F </td><td> Lisp variable </td><td> ? </td><td> </td><td> see manual pages <a href="#page22">22</a>, <a href="#page69">69</a> </td></tr> <td>Lisp variable </td>
<tr><td> ADD1 </td><td> Host lambda function </td><td> ? </td><td> </td><td> ? </td></tr> <td>? </td>
<tr><td> AND </td><td> Host lambda function </td><td> ? </td><td> PREDICATE </td><td> <code>T</code> if and only if none of my <code>args</code> evaluate to either <code>F</code> or <code>NIL</code>, else <code>F</code>. In <code>beowulf.host</code> principally because I dont yet feel confident to define varargs functions in Lisp. </td></tr> <td> </td>
<tr><td> APPEND </td><td> Lisp lambda function </td><td> ? </td><td> </td><td> see manual pages <a href="#page11">11</a>, <a href="#page61">61</a> </td></tr> <td>see manual pages <a href="#page22">22</a>, <a href="#page69">69</a> </td>
<tr><td> APPLY </td><td> Host lambda function </td><td> ? </td><td> </td><td> Apply this <code>function</code> to these <code>arguments</code> in this <code>environment</code> and return the result. For bootstrapping, at least, a version of APPLY written in Clojure. All args are assumed to be symbols or <code>beowulf.cons-cell/ConsCell</code> objects. See page 13 of the Lisp 1.5 Programmers Manual. </td></tr> </tr>
<tr><td> ASSOC </td><td> Lisp lambda function, Host lambda function </td><td> ? </td><td> ? </td><td> If a is an association list such as the one formed by PAIRLIS in the above example, then assoc will produce the first pair whose first term is x. Thus it is a table searching function. All args are assumed to be <code>beowulf.cons-cell/ConsCell</code> objects. See page 12 of the Lisp 1.5 Programmers Manual. <strong>NOTE THAT</strong> this function is overridden by an implementation in Lisp, but is currently still present for bootstrapping. </td></tr> <tr>
<tr><td> ATOM </td><td> Host lambda function </td><td> ? </td><td> PREDICATE </td><td> Returns <code>T</code> if and only if the argument <code>x</code> is bound to an atom; else <code>F</code>. It is not clear to me from the documentation whether <code>(ATOM 7)</code> should return <code>T</code> or <code>F</code>. Im going to assume <code>T</code>. </td></tr> <td>T </td>
<tr><td> CAR </td><td> Host lambda function </td><td> ? </td><td> </td><td> Return the item indicated by the first pointer of a pair. NIL is treated specially: the CAR of NIL is NIL. </td></tr> <td>Lisp variable </td>
<tr><td> CAAAAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>? </td>
<tr><td> CAAADR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td> </td>
<tr><td> CAAAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>see manual pages <a href="#page22">22</a>, <a href="#page69">69</a> </td>
<tr><td> CAADAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> </tr>
<tr><td> CAADDR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <tr>
<tr><td> CAADR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>F </td>
<tr><td> CAAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>Lisp variable </td>
<tr><td> CADAAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>? </td>
<tr><td> CADADR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td> </td>
<tr><td> CADAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>see manual pages <a href="#page22">22</a>, <a href="#page69">69</a> </td>
<tr><td> CADDAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> </tr>
<tr><td> CADDDR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <tr>
<tr><td> CADDR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>ADD1 </td>
<tr><td> CADR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>Host lambda function </td>
<tr><td> CDAAAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>? </td>
<tr><td> CDAADR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td> </td>
<tr><td> CDAAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>? </td>
<tr><td> CDADAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> </tr>
<tr><td> CDADDR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <tr>
<tr><td> CDADR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>AND </td>
<tr><td> CDAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>Host lambda function </td>
<tr><td> CDDAAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>? </td>
<tr><td> CDDADR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>PREDICATE </td>
<tr><td> CDDAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td><code>T</code> if and only if none of my <code>args</code> evaluate to either <code>F</code> or <code>NIL</code>, else <code>F</code>. In <code>beowulf.host</code> principally because I dont yet feel confident to define varargs functions in Lisp. </td>
<tr><td> CDDDAR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> </tr>
<tr><td> CDDDDR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <tr>
<tr><td> CDDDR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>APPEND </td>
<tr><td> CDDR </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>Lisp lambda function </td>
<tr><td> CDR </td><td> Host lambda function </td><td> ? </td><td> </td><td> Return the item indicated by the second pointer of a pair. NIL is treated specially: the CDR of NIL is NIL. </td></tr> <td>? </td>
<tr><td> CONS </td><td> Host lambda function </td><td> ? </td><td> </td><td> Construct a new instance of cons cell with this <code>car</code> and <code>cdr</code>. </td></tr> <td> </td>
<tr><td> CONSP </td><td> Host lambda function </td><td> ? </td><td> ? </td><td> Return <code>T</code> if object <code>o</code> is a cons cell, else <code>F</code>. <strong>NOTE THAT</strong> this is an extension function, not available in strct mode. I believe that Lisp 1.5 did not have any mechanism for testing whether an argument was, or was not, a cons cell. </td></tr> <td>see manual pages <a href="#page11">11</a>, <a href="#page61">61</a> </td>
<tr><td> COPY </td><td> Lisp lambda function </td><td> ? </td><td> </td><td> see manual pages <a href="#page62">62</a> </td></tr> </tr>
<tr><td> DEFINE </td><td> Host lambda function </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> Bootstrap-only version of <code>DEFINE</code> which, post boostrap, can be overwritten in LISP. The single argument to <code>DEFINE</code> should be an association list of symbols to lambda functions. See page 58 of the manual. </td></tr> <tr>
<tr><td> DIFFERENCE </td><td> Host lambda function </td><td> ? </td><td> </td><td> ? </td></tr> <td>APPLY </td>
<tr><td> DIVIDE </td><td> Lisp lambda function </td><td> ? </td><td> </td><td> see manual pages <a href="#page26">26</a>, <a href="#page64">64</a> </td></tr> <td>Host lambda function </td>
<tr><td> DOC </td><td> Host lambda function </td><td> ? </td><td> ? </td><td> Open the page for this <code>symbol</code> in the Lisp 1.5 manual, if known, in the default web browser. <strong>NOTE THAT</strong> this is an extension function, not available in strct mode. </td></tr> <td>? </td>
<tr><td> EFFACE </td><td> Lisp lambda function </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> see manual pages <a href="#page63">63</a> </td></tr> <td> </td>
<tr><td> ERROR </td><td> Host lambda function </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> Throw an error </td></tr> <td>Apply this <code>function</code> to these <code>arguments</code> in this <code>environment</code> and return the result. For bootstrapping, at least, a version of APPLY written in Clojure. All args are assumed to be symbols or <code>beowulf.cons-cell/ConsCell</code> objects. See page 13 of the Lisp 1.5 Programmers Manual. </td>
<tr><td> EQ </td><td> Host lambda function </td><td> ? </td><td> PREDICATE </td><td> Returns <code>T</code> if and only if both <code>x</code> and <code>y</code> are bound to the same atom, else <code>NIL</code>. </td></tr> </tr>
<tr><td> EQUAL </td><td> Host lambda function </td><td> ? </td><td> PREDICATE </td><td> This is a predicate that is true if its two arguments are identical S-expressions, and false if they are different. (The elementary predicate <code>EQ</code> is defined only for atomic arguments.) The definition of <code>EQUAL</code> is an example of a conditional expression inside a conditional expression. NOTE: returns <code>F</code> on failure, not <code>NIL</code> </td></tr> <tr>
<tr><td> EVAL </td><td> Host lambda function </td><td> ? </td><td> </td><td> Evaluate this <code>expr</code> and return the result. If <code>environment</code> is not passed, it defaults to the current value of the global object list. The <code>depth</code> argument is part of the tracing system and should not be set by user code. All args are assumed to be numbers, symbols or <code>beowulf.cons-cell/ConsCell</code> objects. However, if called with just a single arg, <code>expr</code>, Ill assume its being called from the Clojure REPL and will coerce the <code>expr</code> to <code>ConsCell</code>. </td></tr> <td>ASSOC </td>
<tr><td> FACTORIAL </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>Lisp lambda function, Host lambda function </td>
<tr><td> FIXP </td><td> Host lambda function </td><td> ? </td><td> PREDICATE </td><td> ? </td></tr> <td>? </td>
<tr><td> GENSYM </td><td> Host lambda function </td><td> ? </td><td> </td><td> Generate a unique symbol. </td></tr> <td>? </td>
<tr><td> GET </td><td> Host lambda function </td><td> ? </td><td> </td><td> From the manual: <code>get</code> is somewhat like <code>prop</code>; however its value is car of the rest of the list if the <code>indicator</code> is found, and NIL otherwise. Its clear that <code>GET</code> is expected to be defined in terms of <code>PROP</code>, but we cant implement <code>PROP</code> here because we lack <code>EVAL</code>; and we cant have <code>EVAL</code> here because both it and <code>APPLY</code> depends on <code>GET</code>. OK, Its worse than that: the statement of the definition of <code>GET</code> (and of) <code>PROP</code> on page 59 says that the first argument to each must be a list; But the in the definition of <code>ASSOC</code> on page 70, when <code>GET</code> is called its first argument is always an atom. Since its <code>ASSOC</code> and <code>EVAL</code> which I need to make work, Im going to assume that page 59 is wrong. </td></tr> <td>If a is an association list such as the one formed by PAIRLIS in the above example, then assoc will produce the first pair whose first term is x. Thus it is a table searching function. All args are assumed to be <code>beowulf.cons-cell/ConsCell</code> objects. See page 12 of the Lisp 1.5 Programmers Manual. <strong>NOTE THAT</strong> this function is overridden by an implementation in Lisp, but is currently still present for bootstrapping. </td>
<tr><td> GREATERP </td><td> Host lambda function </td><td> ? </td><td> PREDICATE </td><td> ? </td></tr> </tr>
<tr><td> INTEROP </td><td> Host lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <tr>
<tr><td> INTERSECTION </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>ATOM </td>
<tr><td> LENGTH </td><td> Lisp lambda function </td><td> ? </td><td> </td><td> see manual pages <a href="#page62">62</a> </td></tr> <td>Host lambda function </td>
<tr><td> LESSP </td><td> Host lambda function </td><td> ? </td><td> PREDICATE </td><td> ? </td></tr> <td>? </td>
<tr><td> MAPLIST </td><td> Lisp lambda function </td><td> ? </td><td> FUNCTIONAL </td><td> see manual pages <a href="#page20">20</a>, <a href="#page21">21</a>, <a href="#page63">63</a> </td></tr> <td>PREDICATE </td>
<tr><td> MEMBER </td><td> Lisp lambda function </td><td> ? </td><td> PREDICATE </td><td> see manual pages <a href="#page11">11</a>, <a href="#page62">62</a> </td></tr> <td>Returns <code>T</code> if and only if the argument <code>x</code> is bound to an atom; else <code>F</code>. It is not clear to me from the documentation whether <code>(ATOM 7)</code> should return <code>T</code> or <code>F</code>. Im going to assume <code>T</code>. </td>
<tr><td> MINUSP </td><td> Lisp lambda function </td><td> ? </td><td> PREDICATE </td><td> see manual pages <a href="#page26">26</a>, <a href="#page64">64</a> </td></tr> </tr>
<tr><td> NOT </td><td> Lisp lambda function </td><td> ? </td><td> PREDICATE </td><td> see manual pages <a href="#page21">21</a>, <a href="#page23">23</a>, <a href="#page58">58</a> </td></tr> <tr>
<tr><td> NULL </td><td> Lisp lambda function </td><td> ? </td><td> PREDICATE </td><td> see manual pages <a href="#page11">11</a>, <a href="#page57">57</a> </td></tr> <td>CAR </td>
<tr><td> NUMBERP </td><td> Host lambda function </td><td> ? </td><td> PREDICATE </td><td> ? </td></tr> <td>Host lambda function </td>
<tr><td> OBLIST </td><td> Host lambda function </td><td> ? </td><td> </td><td> Return a list of the symbols currently bound on the object list. <strong>NOTE THAT</strong> in the Lisp 1.5 manual, footnote at the bottom of page 69, it implies that an argument can be passed but Im not sure of the semantics of this. </td></tr> <td>? </td>
<tr><td> ONEP </td><td> Lisp lambda function </td><td> ? </td><td> PREDICATE </td><td> see manual pages <a href="#page26">26</a>, <a href="#page64">64</a> </td></tr> <td> </td>
<tr><td> OR </td><td> Host lambda function </td><td> ? </td><td> PREDICATE </td><td> <code>T</code> if and only if at least one of my <code>args</code> evaluates to something other than either <code>F</code> or <code>NIL</code>, else <code>F</code>. In <code>beowulf.host</code> principally because I dont yet feel confident to define varargs functions in Lisp. </td></tr> <td>Return the item indicated by the first pointer of a pair. NIL is treated specially: the CAR of NIL is NIL. </td>
<tr><td> PAIR </td><td> Lisp lambda function </td><td> ? </td><td> </td><td> see manual pages <a href="#page60">60</a> </td></tr> </tr>
<tr><td> PAIRLIS </td><td> Lisp lambda function, Host lambda function </td><td> ? </td><td> ? </td><td> This function gives the list of pairs of corresponding elements of the lists <code>x</code> and <code>y</code>, and APPENDs this to the list <code>a</code>. The resultant list of pairs, which is like a table with two columns, is called an association list. Eessentially, it builds the environment on the stack, implementing shallow binding. All args are assumed to be <code>beowulf.cons-cell/ConsCell</code> objects. See page 12 of the Lisp 1.5 Programmers Manual. <strong>NOTE THAT</strong> this function is overridden by an implementation in Lisp, but is currently still present for bootstrapping. </td></tr> <tr>
<tr><td> PLUS </td><td> Host lambda function </td><td> ? </td><td> </td><td> ? </td></tr> <td>CAAAAR </td>
<tr><td> PRETTY </td><td> </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>Lisp lambda function </td>
<tr><td> PRINT </td><td> </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> see manual pages <a href="#page65">65</a>, <a href="#page84">84</a> </td></tr> <td>? </td>
<tr><td> PROG </td><td> Host nlambda function </td><td> ? </td><td> </td><td> The accursed <code>PROG</code> feature. See page 71 of the manual. Lisp 1.5 introduced <code>PROG</code>, and most Lisps have been stuck with it ever since. It introduces imperative programming into what should be a pure functional language, and consequently its going to be a pig to implement. Broadly, <code>PROG</code> is a variadic pseudo function called as a <code>FEXPR</code> (or possibly an <code>FSUBR</code>, although Im not presently sure that would even work.) The arguments, which are unevaluated, are a list of forms, the first of which is expected to be a list of symbols which will be treated as names of variables within the program, and the rest of which (the program body) are either lists or symbols. Lists are treated as Lisp expressions which may be evaulated in turn. Symbols are treated as targets for the <code>GO</code> statement. <strong>GO:</strong> A <code>GO</code> statement takes the form of <code>(GO target)</code>, where <code>target</code> should be one of the symbols which occur at top level among that particular invocation of <code>PROG</code>s arguments. A <code>GO</code> statement may occur at top level in a PROG, or in a clause of a <code>COND</code> statement in a <code>PROG</code>, but not in a function called from the <code>PROG</code> statement. When a <code>GO</code> statement is evaluated, execution should transfer immediately to the expression which is the argument list immediately following the symbol which is its target. If the target is not found, an error with the code <code>A6</code> should be thrown. <strong>RETURN:</strong> A <code>RETURN</code> statement takes the form <code>(RETURN value)</code>, where <code>value</code> is any value. Following the evaluation of a <code>RETURN</code> statement, the <code>PROG</code> should immediately exit without executing any further expressions, returning the value. <strong>SET and SETQ:</strong> In addition to the above, if a <code>SET</code> or <code>SETQ</code> expression is encountered in any expression within the <code>PROG</code> body, it should affect not the global object list but instead only the local variables of the program. <strong>COND:</strong> In <strong>strict</strong> mode, when in normal execution, a <code>COND</code> statement none of whose clauses match should not return <code>NIL</code> but should throw an error with the code <code>A3</code><em>except</em> that inside a <code>PROG</code> body, it should not do so. <em>sigh</em>. <strong>Flow of control:</strong> Apart from the exceptions specified above, expressions in the program body are evaluated sequentially. If execution reaches the end of the program body, <code>NIL</code> is returned. Got all that? Good. </td></tr> <td>? </td>
<tr><td> PROP </td><td> Lisp lambda function </td><td> ? </td><td> FUNCTIONAL </td><td> see manual pages <a href="#page59">59</a> </td></tr> <td>? </td>
<tr><td> QUOTE </td><td> Lisp lambda function </td><td> ? </td><td> </td><td> see manual pages <a href="#page10">10</a>, <a href="#page22">22</a>, <a href="#page71">71</a> </td></tr> </tr>
<tr><td> QUOTIENT </td><td> Host lambda function </td><td> ? </td><td> </td><td> Im not certain from the documentation whether Lisp 1.5 <code>QUOTIENT</code> returned the integer part of the quotient, or a realnum representing the whole quotient. I am for now implementing the latter. </td></tr> <tr>
<tr><td> RANGE </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>CAAADR </td>
<tr><td> READ </td><td> Host lambda function </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> An implementation of a Lisp reader sufficient for bootstrapping; not necessarily the final Lisp reader. <code>input</code> should be either a string representation of a LISP expression, or else an input stream. A single form will be read. </td></tr> <td>Lisp lambda function </td>
<tr><td> REMAINDER </td><td> Host lambda function </td><td> ? </td><td> </td><td> ? </td></tr> <td>? </td>
<tr><td> REPEAT </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>? </td>
<tr><td> RPLACA </td><td> Host lambda function </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> Replace the CAR pointer of this <code>cell</code> with this <code>value</code>. Dangerous, should really not exist, but does in Lisp 1.5 (and was important for some performance hacks in early Lisps) </td></tr> <td>? </td>
<tr><td> RPLACD </td><td> Host lambda function </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> Replace the CDR pointer of this <code>cell</code> with this <code>value</code>. Dangerous, should really not exist, but does in Lisp 1.5 (and was important for some performance hacks in early Lisps) </td></tr> </tr>
<tr><td> SEARCH </td><td> Lisp lambda function </td><td> ? </td><td> FUNCTIONAL </td><td> see manual pages <a href="#page63">63</a> </td></tr> <tr>
<tr><td> SET </td><td> Host lambda function </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> Implementation of SET in Clojure. Add to the <code>oblist</code> a binding of the value of <code>var</code> to the value of <code>val</code>. NOTE WELL: this is not SETQ! </td></tr> <td>CAAAR </td>
<tr><td> SUB1 </td><td> Lisp lambda function, Host lambda function </td><td> ? </td><td> </td><td> ? </td></tr> <td>Lisp lambda function </td>
<tr><td> SUB2 </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>? </td>
<tr><td> SUBLIS </td><td> Lisp lambda function </td><td> ? </td><td> </td><td> see manual pages <a href="#page12">12</a>, <a href="#page61">61</a> </td></tr> <td>? </td>
<tr><td> SUBST </td><td> Lisp lambda function </td><td> ? </td><td> </td><td> see manual pages <a href="#page11">11</a>, <a href="#page61">61</a> </td></tr> <td>? </td>
<tr><td> SYSIN </td><td> Host lambda function </td><td> ? </td><td> ? </td><td> Read the contents of the file at this <code>filename</code> into the object list. If the file is not a valid Beowulf sysout file, this will probably corrupt the system, you have been warned. File paths will be considered relative to the filepath set when starting Lisp. It is intended that sysout files can be read both from resources within the jar file, and from the file system. If a named file exists in both the file system and the resources, the file system will be preferred. <strong>NOTE THAT</strong> if the provided <code>filename</code> does not end with <code>.lsp</code> (which, if youre writing it from the Lisp REPL, it wont), the extension <code>.lsp</code> will be appended. <strong>NOTE THAT</strong> this is an extension function, not available in strct mode. </td></tr> </tr>
<tr><td> SYSOUT </td><td> Host lambda function </td><td> ? </td><td> ? </td><td> Dump the current content of the object list to file. If no <code>filepath</code> is specified, a file name will be constructed of the symbol <code>Sysout</code> and the current date. File paths will be considered relative to the filepath set when starting Lisp. <strong>NOTE THAT</strong> this is an extension function, not available in strct mode. </td></tr> <tr>
<tr><td> TERPRI </td><td> </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> see manual pages <a href="#page65">65</a>, <a href="#page84">84</a> </td></tr> <td>CAADAR </td>
<tr><td> TIMES </td><td> Host lambda function </td><td> ? </td><td> </td><td> ? </td></tr> <td>Lisp lambda function </td>
<tr><td> TRACE </td><td> Host lambda function </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> Add this <code>s</code> to the set of symbols currently being traced. If <code>s</code> is not a symbol or sequence of symbols, does nothing. </td></tr> <td>? </td>
<tr><td> UNION </td><td> Lisp lambda function </td><td> ? </td><td> ? </td><td> ? </td></tr> <td>? </td>
<tr><td> UNTRACE </td><td> Host lambda function </td><td> ? </td><td> PSEUDO-FUNCTION </td><td> Remove this <code>s</code> from the set of symbols currently being traced. If <code>s</code> is not a symbol or sequence of symbols, does nothing. </td></tr> <td>? </td>
<tr><td> ZEROP </td><td> Lisp lambda function </td><td> ? </td><td> PREDICATE </td><td> see manual pages <a href="#page26">26</a>, <a href="#page64">64</a> </td></tr> </tr>
<tr>
<td>CAADDR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CAADR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CAAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CADAAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CADADR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CADAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CADDAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CADDDR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CADDR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CADR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDAAAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDAADR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDAAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDADAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDADDR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDADR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDDAAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDDADR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDDAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDDDAR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDDDDR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDDDR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDDR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>CDR </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>Return the item indicated by the second pointer of a pair. NIL is treated specially: the CDR of NIL is NIL. </td>
</tr>
<tr>
<td>CONS </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>Construct a new instance of cons cell with this <code>car</code> and <code>cdr</code>. </td>
</tr>
<tr>
<td>CONSP </td>
<td>Host lambda function </td>
<td>? </td>
<td>? </td>
<td>Return <code>T</code> if object <code>o</code> is a cons cell, else <code>F</code>. <strong>NOTE THAT</strong> this is an extension function, not available in strct mode. I believe that Lisp 1.5 did not have any mechanism for testing whether an argument was, or was not, a cons cell. </td>
</tr>
<tr>
<td>COPY </td>
<td>Lisp lambda function </td>
<td>? </td>
<td> </td>
<td>see manual pages <a href="#page62">62</a> </td>
</tr>
<tr>
<td>DEFINE </td>
<td>Host lambda function </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>Bootstrap-only version of <code>DEFINE</code> which, post boostrap, can be overwritten in LISP. The single argument to <code>DEFINE</code> should be an association list of symbols to lambda functions. See page 58 of the manual. </td>
</tr>
<tr>
<td>DIFFERENCE </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>? </td>
</tr>
<tr>
<td>DIVIDE </td>
<td>Lisp lambda function </td>
<td>? </td>
<td> </td>
<td>see manual pages <a href="#page26">26</a>, <a href="#page64">64</a> </td>
</tr>
<tr>
<td>DOC </td>
<td>Host lambda function </td>
<td>? </td>
<td>? </td>
<td>Open the page for this <code>symbol</code> in the Lisp 1.5 manual, if known, in the default web browser. <strong>NOTE THAT</strong> this is an extension function, not available in strct mode. </td>
</tr>
<tr>
<td>EFFACE </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>see manual pages <a href="#page63">63</a> </td>
</tr>
<tr>
<td>ERROR </td>
<td>Host lambda function </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>Throw an error </td>
</tr>
<tr>
<td>EQ </td>
<td>Host lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>Returns <code>T</code> if and only if both <code>x</code> and <code>y</code> are bound to the same atom, else <code>NIL</code>. </td>
</tr>
<tr>
<td>EQUAL </td>
<td>Host lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>This is a predicate that is true if its two arguments are identical S-expressions, and false if they are different. (The elementary predicate <code>EQ</code> is defined only for atomic arguments.) The definition of <code>EQUAL</code> is an example of a conditional expression inside a conditional expression. NOTE: returns <code>F</code> on failure, not <code>NIL</code> </td>
</tr>
<tr>
<td>EVAL </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>Evaluate this <code>expr</code> and return the result. If <code>environment</code> is not passed, it defaults to the current value of the global object list. The <code>depth</code> argument is part of the tracing system and should not be set by user code. All args are assumed to be numbers, symbols or <code>beowulf.cons-cell/ConsCell</code> objects. However, if called with just a single arg, <code>expr</code>, Ill assume its being called from the Clojure REPL and will coerce the <code>expr</code> to <code>ConsCell</code>. </td>
</tr>
<tr>
<td>FACTORIAL </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>FIXP </td>
<td>Host lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>? </td>
</tr>
<tr>
<td>GENSYM </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>Generate a unique symbol. </td>
</tr>
<tr>
<td>GET </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>From the manual: <code>get</code> is somewhat like <code>prop</code>; however its value is car of the rest of the list if the <code>indicator</code> is found, and NIL otherwise. Its clear that <code>GET</code> is expected to be defined in terms of <code>PROP</code>, but we cant implement <code>PROP</code> here because we lack <code>EVAL</code>; and we cant have <code>EVAL</code> here because both it and <code>APPLY</code> depends on <code>GET</code>. OK, Its worse than that: the statement of the definition of <code>GET</code> (and of) <code>PROP</code> on page 59 says that the first argument to each must be a list; But the in the definition of <code>ASSOC</code> on page 70, when <code>GET</code> is called its first argument is always an atom. Since its <code>ASSOC</code> and <code>EVAL</code> which I need to make work, Im going to assume that page 59 is wrong. </td>
</tr>
<tr>
<td>GREATERP </td>
<td>Host lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>? </td>
</tr>
<tr>
<td>INTEROP </td>
<td>Host lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>INTERSECTION </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>LENGTH </td>
<td>Lisp lambda function </td>
<td>? </td>
<td> </td>
<td>see manual pages <a href="#page62">62</a> </td>
</tr>
<tr>
<td>LESSP </td>
<td>Host lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>? </td>
</tr>
<tr>
<td>MAPLIST </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>FUNCTIONAL </td>
<td>see manual pages <a href="#page20">20</a>, <a href="#page21">21</a>, <a href="#page63">63</a> </td>
</tr>
<tr>
<td>MEMBER </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>see manual pages <a href="#page11">11</a>, <a href="#page62">62</a> </td>
</tr>
<tr>
<td>MINUSP </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>see manual pages <a href="#page26">26</a>, <a href="#page64">64</a> </td>
</tr>
<tr>
<td>NOT </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>see manual pages <a href="#page21">21</a>, <a href="#page23">23</a>, <a href="#page58">58</a> </td>
</tr>
<tr>
<td>NULL </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>see manual pages <a href="#page11">11</a>, <a href="#page57">57</a> </td>
</tr>
<tr>
<td>NUMBERP </td>
<td>Host lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>? </td>
</tr>
<tr>
<td>OBLIST </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>Return a list of the symbols currently bound on the object list. <strong>NOTE THAT</strong> in the Lisp 1.5 manual, footnote at the bottom of page 69, it implies that an argument can be passed but Im not sure of the semantics of this. </td>
</tr>
<tr>
<td>ONEP </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>see manual pages <a href="#page26">26</a>, <a href="#page64">64</a> </td>
</tr>
<tr>
<td>OR </td>
<td>Host lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td><code>T</code> if and only if at least one of my <code>args</code> evaluates to something other than either <code>F</code> or <code>NIL</code>, else <code>F</code>. In <code>beowulf.host</code> principally because I dont yet feel confident to define varargs functions in Lisp. </td>
</tr>
<tr>
<td>PAIR </td>
<td>Lisp lambda function </td>
<td>? </td>
<td> </td>
<td>see manual pages <a href="#page60">60</a> </td>
</tr>
<tr>
<td>PAIRLIS </td>
<td>Lisp lambda function, Host lambda function </td>
<td>? </td>
<td>? </td>
<td>This function gives the list of pairs of corresponding elements of the lists <code>x</code> and <code>y</code>, and APPENDs this to the list <code>a</code>. The resultant list of pairs, which is like a table with two columns, is called an association list. Eessentially, it builds the environment on the stack, implementing shallow binding. All args are assumed to be <code>beowulf.cons-cell/ConsCell</code> objects. See page 12 of the Lisp 1.5 Programmers Manual. <strong>NOTE THAT</strong> this function is overridden by an implementation in Lisp, but is currently still present for bootstrapping. </td>
</tr>
<tr>
<td>PLUS </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>? </td>
</tr>
<tr>
<td>PRETTY </td>
<td> </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>PRINT </td>
<td> </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>see manual pages <a href="#page65">65</a>, <a href="#page84">84</a> </td>
</tr>
<tr>
<td>PROG </td>
<td>Host nlambda function </td>
<td>? </td>
<td> </td>
<td>The accursed <code>PROG</code> feature. See page 71 of the manual. Lisp 1.5 introduced <code>PROG</code>, and most Lisps have been stuck with it ever since. It introduces imperative programming into what should be a pure functional language, and consequently its going to be a pig to implement. Broadly, <code>PROG</code> is a variadic pseudo function called as a <code>FEXPR</code> (or possibly an <code>FSUBR</code>, although Im not presently sure that would even work.) The arguments, which are unevaluated, are a list of forms, the first of which is expected to be a list of symbols which will be treated as names of variables within the program, and the rest of which (the program body) are either lists or symbols. Lists are treated as Lisp expressions which may be evaulated in turn. Symbols are treated as targets for the <code>GO</code> statement. <strong>GO:</strong> A <code>GO</code> statement takes the form of <code>(GO target)</code>, where <code>target</code> should be one of the symbols which occur at top level among that particular invocation of <code>PROG</code>s arguments. A <code>GO</code> statement may occur at top level in a PROG, or in a clause of a <code>COND</code> statement in a <code>PROG</code>, but not in a function called from the <code>PROG</code> statement. When a <code>GO</code> statement is evaluated, execution should transfer immediately to the expression which is the argument list immediately following the symbol which is its target. If the target is not found, an error with the code <code>A6</code> should be thrown. <strong>RETURN:</strong> A <code>RETURN</code> statement takes the form <code>(RETURN value)</code>, where <code>value</code> is any value. Following the evaluation of a <code>RETURN</code> statement, the <code>PROG</code> should immediately exit without executing any further expressions, returning the value. <strong>SET and SETQ:</strong> In addition to the above, if a <code>SET</code> or <code>SETQ</code> expression is encountered in any expression within the <code>PROG</code> body, it should affect not the global object list but instead only the local variables of the program. <strong>COND:</strong> In <strong>strict</strong> mode, when in normal execution, a <code>COND</code> statement none of whose clauses match should not return <code>NIL</code> but should throw an error with the code <code>A3</code><em>except</em> that inside a <code>PROG</code> body, it should not do so. <em>sigh</em>. <strong>Flow of control:</strong> Apart from the exceptions specified above, expressions in the program body are evaluated sequentially. If execution reaches the end of the program body, <code>NIL</code> is returned. Got all that? Good. </td>
</tr>
<tr>
<td>PROP </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>FUNCTIONAL </td>
<td>see manual pages <a href="#page59">59</a> </td>
</tr>
<tr>
<td>QUOTE </td>
<td>Lisp lambda function </td>
<td>? </td>
<td> </td>
<td>see manual pages <a href="#page10">10</a>, <a href="#page22">22</a>, <a href="#page71">71</a> </td>
</tr>
<tr>
<td>QUOTIENT </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>Im not certain from the documentation whether Lisp 1.5 <code>QUOTIENT</code> returned the integer part of the quotient, or a realnum representing the whole quotient. I am for now implementing the latter. </td>
</tr>
<tr>
<td>RANGE </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>READ </td>
<td>Host lambda function </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>An implementation of a Lisp reader sufficient for bootstrapping; not necessarily the final Lisp reader. <code>input</code> should be either a string representation of a LISP expression, or else an input stream. A single form will be read. </td>
</tr>
<tr>
<td>REMAINDER </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>? </td>
</tr>
<tr>
<td>REPEAT </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>RPLACA </td>
<td>Host lambda function </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>Replace the CAR pointer of this <code>cell</code> with this <code>value</code>. Dangerous, should really not exist, but does in Lisp 1.5 (and was important for some performance hacks in early Lisps) </td>
</tr>
<tr>
<td>RPLACD </td>
<td>Host lambda function </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>Replace the CDR pointer of this <code>cell</code> with this <code>value</code>. Dangerous, should really not exist, but does in Lisp 1.5 (and was important for some performance hacks in early Lisps) </td>
</tr>
<tr>
<td>SEARCH </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>FUNCTIONAL </td>
<td>see manual pages <a href="#page63">63</a> </td>
</tr>
<tr>
<td>SET </td>
<td>Host lambda function </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>Implementation of SET in Clojure. Add to the <code>oblist</code> a binding of the value of <code>var</code> to the value of <code>val</code>. NOTE WELL: this is not SETQ! </td>
</tr>
<tr>
<td>SUB1 </td>
<td>Lisp lambda function, Host lambda function </td>
<td>? </td>
<td> </td>
<td>? </td>
</tr>
<tr>
<td>SUB2 </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>SUBLIS </td>
<td>Lisp lambda function </td>
<td>? </td>
<td> </td>
<td>see manual pages <a href="#page12">12</a>, <a href="#page61">61</a> </td>
</tr>
<tr>
<td>SUBST </td>
<td>Lisp lambda function </td>
<td>? </td>
<td> </td>
<td>see manual pages <a href="#page11">11</a>, <a href="#page61">61</a> </td>
</tr>
<tr>
<td>SYSIN </td>
<td>Host lambda function </td>
<td>? </td>
<td>? </td>
<td>Read the contents of the file at this <code>filename</code> into the object list. If the file is not a valid Beowulf sysout file, this will probably corrupt the system, you have been warned. File paths will be considered relative to the filepath set when starting Lisp. It is intended that sysout files can be read both from resources within the jar file, and from the file system. If a named file exists in both the file system and the resources, the file system will be preferred. <strong>NOTE THAT</strong> if the provided <code>filename</code> does not end with <code>.lsp</code> (which, if youre writing it from the Lisp REPL, it wont), the extension <code>.lsp</code> will be appended. <strong>NOTE THAT</strong> this is an extension function, not available in strct mode. </td>
</tr>
<tr>
<td>SYSOUT </td>
<td>Host lambda function </td>
<td>? </td>
<td>? </td>
<td>Dump the current content of the object list to file. If no <code>filepath</code> is specified, a file name will be constructed of the symbol <code>Sysout</code> and the current date. File paths will be considered relative to the filepath set when starting Lisp. <strong>NOTE THAT</strong> this is an extension function, not available in strct mode. </td>
</tr>
<tr>
<td>TERPRI </td>
<td> </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>see manual pages <a href="#page65">65</a>, <a href="#page84">84</a> </td>
</tr>
<tr>
<td>TIMES </td>
<td>Host lambda function </td>
<td>? </td>
<td> </td>
<td>? </td>
</tr>
<tr>
<td>TRACE </td>
<td>Host lambda function </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>Add this <code>s</code> to the set of symbols currently being traced. If <code>s</code> is not a symbol or sequence of symbols, does nothing. </td>
</tr>
<tr>
<td>UNION </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>? </td>
<td>? </td>
</tr>
<tr>
<td>UNTRACE </td>
<td>Host lambda function </td>
<td>? </td>
<td>PSEUDO-FUNCTION </td>
<td>Remove this <code>s</code> from the set of symbols currently being traced. If <code>s</code> is not a symbol or sequence of symbols, does nothing. </td>
</tr>
<tr>
<td>ZEROP </td>
<td>Lisp lambda function </td>
<td>? </td>
<td>PREDICATE </td>
<td>see manual pages <a href="#page26">26</a>, <a href="#page64">64</a> </td>
</tr>
</tbody> </tbody>
</table> </table>
<p>Functions described as Lisp function above are defined in the default sysout file, <code>resources/lisp1.5.lsp</code>, which will be loaded by default unless you specify another initfile on the command line.</p> <p>Functions described as Lisp function above are defined in the default sysout file, <code>resources/lisp1.5.lsp</code>, which will be loaded by default unless you specify another initfile on the command line.</p>
<p>Functions described as Host function are implemented in Clojure, but if youre brave you can redefine them in Lisp and the Lisp definitions will take precedence over the Clojure implementations.</p> <p>Functions described as Host function are implemented in Clojure, but if youre brave you can redefine them in Lisp and the Lisp definitions will take precedence over the Clojure implementations.</p>
<h3><a href="#architectural-plan" id="architectural-plan"></a>Architectural plan</h3> <h3><a href="#architectural-plan" name="architectural-plan"></a>Architectural plan</h3>
<p>Not everything documented in this section is yet built. It indicates the direction of travel and intended destination, not the current state.</p> <p>Not everything documented in this section is yet built. It indicates the direction of travel and intended destination, not the current state.</p>
<h4><a href="#resourceslisp15lsp" id="resourceslisp15lsp"></a>resources/lisp1.5.lsp</h4> <h4><a href="#resources-lisp1-5-lsp" name="resources-lisp1-5-lsp"></a>resources/lisp1.5.lsp</h4>
<p>The objective is to have within <code>resources/lisp1.5.lsp</code>, all those functions defined in the Lisp 1.5 Programmers Manual which can be implemented in Lisp.</p> <p>The objective is to have within <code>resources/lisp1.5.lsp</code>, all those functions defined in the Lisp 1.5 Programmers Manual which can be implemented in Lisp.</p>
<p>This means that, while Beowulf is hosted on Clojure, all that would be required to rehost Lisp 1.5 on a different platform would be to reimplement</p> <p>This means that, while Beowulf is hosted on Clojure, all that would be required to rehost Lisp 1.5 on a different platform would be to reimplement</p>
<ul> <ul>
@ -197,46 +791,45 @@
<li>read.clj</li> <li>read.clj</li>
</ul> </ul>
<p>The objective this is to make it fairly easy to implement Lisp 1.5 on top of any of the many <a href="https://github.com/kanaka/mal">Make A Lisp</a> implementations.</p> <p>The objective this is to make it fairly easy to implement Lisp 1.5 on top of any of the many <a href="https://github.com/kanaka/mal">Make A Lisp</a> implementations.</p>
<h4><a href="#beowulfboostrapclj" id="beowulfboostrapclj"></a>beowulf/boostrap.clj</h4> <h4><a href="#beowulf-boostrap-clj" name="beowulf-boostrap-clj"></a>beowulf/boostrap.clj</h4>
<p>This file is essentially Lisp as defined in Chapter 1 (pages 1-14) of the Lisp 1.5 Programmers Manual; that is to say, a very simple Lisp language, which should, I believe, be sufficient in conjunction with the functions provided by <code>beowulf.host</code>, to bootstrap the full Lisp 1.5 interpreter.</p> <p>This file is essentially Lisp as defined in Chapter 1 (pages 1-14) of the Lisp 1.5 Programmers Manual; that is to say, a very simple Lisp language, which should, I believe, be sufficient in conjunction with the functions provided by <code>beowulf.host</code>, to bootstrap the full Lisp 1.5 interpreter.</p>
<p>In addition it contains the function <code>INTEROP</code>, which allows host language functions to be called from Lisp.</p> <p>In addition it contains the function <code>INTEROP</code>, which allows host language functions to be called from Lisp.</p>
<h4><a href="#beowulfhostclj" id="beowulfhostclj"></a>beowulf/host.clj</h4> <h4><a href="#beowulf-host-clj" name="beowulf-host-clj"></a>beowulf/host.clj</h4>
<p>This file provides Lisp 1.5 functions which cant be (or cant efficiently be) implemented in Lisp 1.5, which therefore need to be implemented in the host language, in this case Clojure.</p> <p>This file provides Lisp 1.5 functions which cant be (or cant efficiently be) implemented in Lisp 1.5, which therefore need to be implemented in the host language, in this case Clojure.</p>
<h4><a href="#beowulfreadclj" id="beowulfreadclj"></a>beowulf/read.clj</h4> <h4><a href="#beowulf-read-clj" name="beowulf-read-clj"></a>beowulf/read.clj</h4>
<p>This file provides the reader required for boostrapping. Its not a bad reader - it provides feedback on errors found in the input - but it isnt the real Lisp reader.</p> <p>This file provides the reader required for boostrapping. Its not a bad reader - it provides feedback on errors found in the input - but it isnt the real Lisp reader.</p>
<p>Intended deviations from the behaviour of the real Lisp reader are as follows:</p> <p>Intended deviations from the behaviour of the real Lisp reader are as follows:</p>
<ol> <ol>
<li>It reads the meta-expression language <code>MEXPR</code> in addition to the symbolic expression language <code>SEXPR</code>, which I do not believe the Lisp 1.5 reader ever did;</li> <li>It reads the meta-expression language <code>MEXPR</code> in addition to the symbolic expression language <code>SEXPR</code>, which I do not believe the Lisp 1.5 reader ever did;</li>
<li>It treats everything between a double semi-colon and an end of line as a comment, as most modern Lisps do; but I do not believe Lisp 1.5 had this feature.</li> <li>It treats everything between a double semi-colon and an end of line as a comment, as most modern Lisps do; but I do not believe Lisp 1.5 had this feature.</li>
</ol> </ol>
<h3><a href="#commentary" id="commentary"></a>Commentary</h3> <h3><a href="#commentary" name="commentary"></a>Commentary</h3>
<p>Whats surprised me in working on this is how much more polished Lisp 1.5 is than legend had led me to believe. The language is remarkably close to <a href="http://www.softwarepreservation.org/projects/LISP/standard_lisp_family/#Portable_Standard_LISP_">Portable Standard Lisp</a> which is in my opinion one of the best and most usable early Lisp implementations. </p> <p>Whats surprised me in working on this is how much more polished Lisp 1.5 is than legend had led me to believe. The language is remarkably close to <a href="http://www.softwarepreservation.org/projects/LISP/standard_lisp_family/#Portable_Standard_LISP_">Portable Standard Lisp</a> which is in my opinion one of the best and most usable early Lisp implementations. </p>
<p>Whats even more surprising is how faithful a reimplementation of Lisp 1.5 the first Lisp dialect I learned, <a href="https://en.wikipedia.org/wiki/Acornsoft_LISP">Acornsoft Lisp</a>, turns out to have been.</p> <p>Whats even more surprising is how faithful a reimplementation of Lisp 1.5 the first Lisp dialect I learned, <a href="https://en.wikipedia.org/wiki/Acornsoft_LISP">Acornsoft Lisp</a>, turns out to have been.</p>
<p>Im convinced you could still use Lisp 1.5 for interesting and useful software (which isnt to say that modern Lisps arent better, but this is software which is almost sixty years old).</p> <p>Im convinced you could still use Lisp 1.5 for interesting and useful software (which isnt to say that modern Lisps arent better, but this is software which is almost sixty years old).</p>
<h2><a href="#installation" id="installation"></a>Installation</h2> <h2><a href="#installation" name="installation"></a>Installation</h2>
<p>Download the latest <a href="https://github.com/simon-brooke/beowulf/releases">release uberjar</a> and run it using:</p> <p>Download the latest <a href="https://github.com/simon-brooke/beowulf/releases">release uberjar</a> and run it using:</p>
<pre><code class="language-bash"> java -jar &lt;path name of uberjar&gt; <pre><code class="bash"> java -jar &lt;path name of uberjar&gt;
</code></pre> </code></pre>
<p>Or clone the source and build it using:</p> <p>Or clone the source and build it using:</p>
<pre><code class="language-bash"> lein uberjar` <pre><code class="bash"> lein uberjar`
</code></pre> </code></pre>
<p>To build it you will require to have <a href="https://leiningen.org/">Leiningen</a> installed.</p> <p>To build it you will require to have <a href="https://leiningen.org/">Leiningen</a> installed.</p>
<h3><a href="#inputoutput" id="inputoutput"></a>Input/output</h3> <h3><a href="#input-output" name="input-output"></a>Input/output</h3>
<p>Lisp 1.5 greatly predates modern computers. It had a facility to print to a line printer, or to punch cards on a punch-card machine, and it had a facility to read system images in from tape; but theres no file I/O as we would currently understand it, and, because there are no character strings and the valid characters within an atom are limited, it isnt easy to compose a sensible filename.</p> <p>Lisp 1.5 greatly predates modern computers. It had a facility to print to a line printer, or to punch cards on a punch-card machine, and it had a facility to read system images in from tape; but theres no file I/O as we would currently understand it, and, because there are no character strings and the valid characters within an atom are limited, it isnt easy to compose a sensible filename.</p>
<p>Ive provided two functions to work around this problem.</p> <p>Ive provided two functions to work around this problem.</p>
<h4><a href="#sysout" id="sysout"></a>SYSOUT</h4> <h4><a href="#sysout" name="sysout"></a>SYSOUT</h4>
<p><code>SYSOUT</code> dumps the global object list to disk as a single S Expression (specifically: an association list). This allows you to persist your session, with all your current work, to disk. The function takes one argument, expected to be a symbol, and, if that argument is provided, writes a file whose name is that symbol with <code>.lsp</code> appended. If no argument is provided, it will construct a filename comprising the token <code>Sysout</code>, followed by the current date, followed by <code>.lsp</code>. In either case the file will be written to the directory given in the FILEPATH argument at startup time, or by default the current directory.</p> <p><code>SYSOUT</code> dumps the global object list to disk as a single S Expression (specifically: an association list). This allows you to persist your session, with all your current work, to disk. The function takes one argument, expected to be a symbol, and, if that argument is provided, writes a file whose name is that symbol with <code>.lsp</code> appended. If no argument is provided, it will construct a filename comprising the token <code>Sysout</code>, followed by the current date, followed by <code>.lsp</code>. In either case the file will be written to the directory given in the FILEPATH argument at startup time, or by default the current directory.</p>
<p>Obviously, <code>SYSOUT</code> may be called interactively (and this is the expected practice).</p> <p>Obviously, <code>SYSOUT</code> may be called interactively (and this is the expected practice).</p>
<h4><a href="#sysin" id="sysin"></a>SYSIN</h4> <h4><a href="#sysin" name="sysin"></a>SYSIN</h4>
<p><code>SYSIN</code> reads a file from disk and overwrites the global object list with its contents. The expected practice is that this will be a file created by <code>SYSOUT</code>. A command line flag <code>--read</code> is provided so that you can specify </p> <p><code>SYSIN</code> reads a file from disk and overwrites the global object list with its contents. The expected practice is that this will be a file created by <code>SYSOUT</code>. A command line flag <code>--read</code> is provided so that you can specify </p>
<h2><a href="#learning-lisp-15" id="learning-lisp-15"></a>Learning Lisp 1.5</h2> <h2><a href="#learning-lisp-1-5" name="learning-lisp-1-5"></a>Learning Lisp 1.5</h2>
<p>The <code>Lisp 1.5 Programmer's Manual</code> is still <a href="https://mitpress.mit.edu/books/lisp-15-programmers-manual">in print, ISBN 13 978-0-262-13011-0</a>; but its also <a href="http://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf">available online</a>.</p> <p>The <code>Lisp 1.5 Programmer's Manual</code> is still <a href="https://mitpress.mit.edu/books/lisp-15-programmers-manual">in print, ISBN 13 978-0-262-13011-0</a>; but its also <a href="http://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf">available online</a>.</p>
<h2><a href="#other-lisp-15-resources" id="other-lisp-15-resources"></a>Other Lisp 1.5 resources</h2> <h2><a href="#other-lisp-1-5-resources" name="other-lisp-1-5-resources"></a>Other Lisp 1.5 resources</h2>
<p>The main resource Im aware of is the Software Preservation Societys site, <a href="http://www.softwarepreservation.org/projects/LISP/lisp1.5">here</a>. It has lots of fascinating stuff including full assembler listings for various obsolete processors, but I failed to find the Lisp source of Lisp functions as a text file, which is why <code>resources/lisp1.5.lsp</code> is largely copytyped and reconstructed from the manual.</p> <p>The main resource Im aware of is the Software Preservation Societys site, <a href="http://www.softwarepreservation.org/projects/LISP/lisp1.5">here</a>. It has lots of fascinating stuff including full assembler listings for various obsolete processors, but I failed to find the Lisp source of Lisp functions as a text file, which is why <code>resources/lisp1.5.lsp</code> is largely copytyped and reconstructed from the manual.</p>
<h3><a href="#other-implementations" id="other-implementations"></a>Other implementations</h3> <h3><a href="#other-implementations" name="other-implementations"></a>Other implementations</h3>
<p>Theres an online (browser native) Lisp 1.5 implementation <a href="https://pages.zick.run/ichigo/">here</a> (source code <a href="https://github.com/zick/IchigoLisp">here</a>). It even has a working compiler!</p> <p>Theres an online (browser native) Lisp 1.5 implementation <a href="https://pages.zick.run/ichigo/">here</a> (source code <a href="https://github.com/zick/IchigoLisp">here</a>). It even has a working compiler!</p>
<h3><a href="#history-resources" id="history-resources"></a>History resources</h3> <h3><a href="#history-resources" name="history-resources"></a>History resources</h3>
<p>Im compiling a <a href="https://simon-brooke.github.io/beowulf/docs/codox/further_reading.html">list of links to historical documents on Lisp 1.5</a>.</p> <p>Im compiling a <a href="https://simon-brooke.github.io/beowulf/docs/further_reading.html">list of links to historical documents on Lisp 1.5</a>.</p>
<h2><a href="#license" id="license"></a>License</h2> <h2><a href="#license" name="license"></a>License</h2>
<p>Copyright © 2019 Simon Brooke. Licensed under the GNU General Public License, version 2.0 or (at your option) any later version.</p> <p>Copyright © 2019 Simon Brooke. Licensed under the GNU General Public License, version 2.0 or (at your option) any later version.</p></div></div></div></body></html>
</div></div></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
codox/intro.html

14
docs/index.html Normal file
View file

@ -0,0 +1,14 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Beowulf: Documentation</title>
<link rel="stylesheet" type="text/css" href="codox/css/default.css" />
</head>
<body>
<h1>Beowulf: Documentation</h1>
<ul>
<li><a href="codox/index.html">Primary documentaion</a></li>
<li><a href="cloverage/index.html">Test coverage</a></li>
</ul>
</body>
</html>

View file

@ -1,12 +1,17 @@
(defproject beowulf "0.3.1-SNAPSHOT" (defproject beowulf "0.3.0"
:aot :all :aot :all
:cloverage {:output "docs/cloverage" :cloverage {:output "docs/cloverage"
:ns-exclude-regex [#"beowulf\.gendoc" #"beowulf\.scratch"]} :ns-exclude-regex [#"beowulf\.gendoc" #"beowulf\.scratch"]}
:codox {:metadata {:doc "**TODO**: write docs" :codox {:html {:transforms [[:head] [:append
[:link {:rel "icon"
:type "image/x-icon"
:href "../img/beowulf_logo_favicon.png"}]]]}
:metadata {:doc "**TODO**: write docs"
:doc/format :markdown} :doc/format :markdown}
:output-path "docs/codox" :output-path "docs/codox"
:source-uri "https://github.com/simon-brooke/beowulf/blob/master/{filepath}#L{line}" :source-uri "https://github.com/simon-brooke/beowulf/blob/master/{filepath}#L{line}"
:themes [:journeyman]} ;; :themes [:journeyman]
}
:description "LISP 1.5 is to all Lisp dialects as Beowulf is to English literature." :description "LISP 1.5 is to all Lisp dialects as Beowulf is to English literature."
:license {:name "GPL-2.0-or-later" :license {:name "GPL-2.0-or-later"
:url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"} :url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"}
@ -18,17 +23,15 @@
[clojure.java-time "1.2.0"] [clojure.java-time "1.2.0"]
[environ "1.2.0"] [environ "1.2.0"]
[instaparse "1.4.12"] [instaparse "1.4.12"]
[org.jline/jline "3.23.0"] ;; [org.jline/jline "3.23.0"]
[com.github.seancorfield/expectations "2.0.165"] [rhizome "0.2.9"] ;; not needed in production builds
;; [rhizome "0.2.9"] ;; not needed in production builds
] ]
:main beowulf.core :main beowulf.core
:plugins [[lein-cloverage "1.2.2"] :plugins [[lein-cloverage "1.2.2"]
[lein-codox "0.10.8"] [lein-codox "0.10.7"]
[lein-environ "1.1.0"]] [lein-environ "1.1.0"]]
:profiles {:jar {:aot :all} :profiles {:jar {:aot :all}
:uberjar {:aot :all} :uberjar {:aot :all}}
:dev {:resource-paths ["resources"]}}
:release-tasks [["vcs" "assert-committed"] :release-tasks [["vcs" "assert-committed"]
["change" "version" "leiningen.release/bump-version" "release"] ["change" "version" "leiningen.release/bump-version" "release"]
["vcs" "commit"] ["vcs" "commit"]
@ -39,4 +42,4 @@
["change" "version" "leiningen.release/bump-version"] ["change" "version" "leiningen.release/bump-version"]
["vcs" "commit"]] ["vcs" "commit"]]
:target-path "target/%s" :target-path "target/%s"
:url "https://github.com/simon-brooke/beowulf") :url "https://github.com/simon-brooke/the-great-game")

View file

@ -1,563 +0,0 @@
body {
font-family: Helvetica, Arial, sans-serif;
font-size: 15px;
color: limegreen;
background-color: black;
}
a {
color: lime;
}
a:active, a:hover {
color: yellowgreen;
}
a:visited {
color: green;
}
pre, code {
font-family: Monaco, DejaVu Sans Mono, Consolas, monospace;
font-size: 9pt;
margin: 15px 0;
color: limegreen;
background-color: #111;
}
h1 {
font-weight: normal;
font-size: 29px;
margin: 10px 0 2px 0;
padding: 0;
}
h2 {
font-weight: normal;
font-size: 25px;
}
th, td {
vertical-align: top;
}
h5.license {
margin: 9px 0 22px 0;
color: lime;
font-weight: normal;
font-size: 12px;
font-style: italic;
}
.document h1, .namespace-index h1 {
font-size: 32px;
margin-top: 12px;
}
#header, #content, .sidebar {
position: fixed;
}
#header {
top: 0;
left: 0;
right: 0;
height: 22px;
color: limegreen;
padding: 5px 7px;
}
#content {
top: 32px;
right: 0;
bottom: 0;
overflow: auto;
background: black;
color: green;
padding: 0 18px;
}
.sidebar {
position: fixed;
top: 32px;
bottom: 0;
overflow: auto;
}
.sidebar.primary {
background: #080808;
border-right: solid 1px forestgreen;
left: 0;
width: 250px;
}
.sidebar.secondary {
background: #111;
border-right: solid 1px darkgreen;
left: 251px;
width: 200px;
}
#content.namespace-index, #content.document {
left: 251px;
}
#content.namespace-docs {
left: 452px;
}
#content.document {
padding-bottom: 10%;
}
#header {
background: #080808;
box-shadow: 0 0 8px rgba(192, 255, 192, 0.4);
z-index: 100;
}
#header h1 {
margin: 0;
padding: 0;
font-size: 18px;
font-weight: lighter;
text-shadow: -1px -1px 0px #333;
}
#header h1 .project-version {
font-weight: normal;
}
.project-version {
padding-left: 0.15em;
}
#header a, .sidebar a {
display: block;
text-decoration: none;
}
#header h2 {
float: right;
font-size: 9pt;
font-weight: normal;
margin: 4px 3px;
padding: 0;
color: #5f5;
}
#header h2 a {
display: inline;
}
.sidebar h3 {
margin: 0;
padding: 10px 13px 0 13px;
font-size: 19px;
font-weight: lighter;
}
.sidebar h3 a {
color: #4f4;
}
.sidebar h3.no-link {
color: green;
}
.sidebar ul {
padding: 7px 0 6px 0;
margin: 0;
}
.sidebar ul.index-link {
padding-bottom: 4px;
}
.sidebar li {
display: block;
vertical-align: middle;
}
.sidebar li a, .sidebar li .no-link {
border-left: 3px solid transparent;
padding: 0 10px;
white-space: nowrap;
}
.sidebar li .no-link {
display: block;
color: #7F7;
font-style: italic;
}
.sidebar li .inner {
display: inline-block;
padding-top: 7px;
height: 24px;
}
.sidebar li a, .sidebar li .tree {
height: 31px;
}
.depth-1 .inner { padding-left: 2px; }
.depth-2 .inner { padding-left: 6px; }
.depth-3 .inner { padding-left: 20px; }
.depth-4 .inner { padding-left: 34px; }
.depth-5 .inner { padding-left: 48px; }
.depth-6 .inner { padding-left: 62px; }
.sidebar li .tree {
display: block;
float: left;
position: relative;
top: -10px;
margin: 0 4px 0 0;
padding: 0;
}
.sidebar li.depth-1 .tree {
display: none;
}
.sidebar li .tree .top, .sidebar li .tree .bottom {
display: block;
margin: 0;
padding: 0;
width: 7px;
}
.sidebar li .tree .top {
border-left: 1px solid yellowgreen;
border-bottom: 1px solid yellowgreen;
height: 19px;
}
.sidebar li .tree .bottom {
height: 22px;
}
.sidebar li.branch .tree .bottom {
border-left: 1px solid yellowgreen;
}
.sidebar.primary li.current a {
border-left: 3px solid goldenrod;
color: goldenrod;
}
.sidebar.secondary li.current a {
border-left: 3px solid yellow;
color: yellow;
}
.namespace-index h2 {
margin: 30px 0 0 0;
}
.namespace-index h3 {
font-size: 16px;
font-weight: bold;
margin-bottom: 0;
}
.namespace-index .topics {
padding-left: 30px;
margin: 11px 0 0 0;
}
.namespace-index .topics li {
padding: 5px 0;
}
.namespace-docs h3 {
font-size: 18px;
font-weight: bold;
}
.public h3 {
margin: 0;
float: left;
}
.usage {
clear: both;
}
.public {
margin: 0;
border-top: 1px solid lime;
padding-top: 14px;
padding-bottom: 6px;
}
.public:last-child {
margin-bottom: 20%;
}
.members .public:last-child {
margin-bottom: 0;
}
.members {
margin: 15px 0;
}
.members h4 {
color: lime;
font-weight: normal;
font-variant: small-caps;
margin: 0 0 5px 0;
}
.members .inner {
padding-top: 5px;
padding-left: 12px;
margin-top: 2px;
margin-left: 7px;
border-left: 1px solid #5f5;
}
#content .members .inner h3 {
font-size: 12pt;
}
.members .public {
border-top: none;
margin-top: 0;
padding-top: 6px;
padding-bottom: 0;
}
.members .public:first-child {
padding-top: 0;
}
h4.type,
h4.dynamic,
h4.added,
h4.deprecated {
float: left;
margin: 3px 10px 15px 0;
font-size: 15px;
font-weight: bold;
font-variant: small-caps;
}
.public h4.type,
.public h4.dynamic,
.public h4.added,
.public h4.deprecated {
font-size: 13px;
font-weight: bold;
margin: 3px 0 0 10px;
}
.members h4.type,
.members h4.added,
.members h4.deprecated {
margin-top: 1px;
}
h4.type {
color: #717171;
}
h4.dynamic {
color: #9933aa;
}
h4.added {
color: #7acc32;
}
h4.deprecated {
color: #880000;
}
.namespace {
margin-bottom: 30px;
}
.namespace:last-child {
margin-bottom: 10%;
}
.index {
padding: 0;
font-size: 80%;
margin: 15px 0;
line-height: 16px;
}
.index * {
display: inline;
}
.index p {
padding-right: 3px;
}
.index li {
padding-right: 5px;
}
.index ul {
padding-left: 0;
}
.type-sig {
clear: both;
color: goldenrod;
}
.type-sig pre {
padding-top: 10px;
margin: 0;
}
.usage code {
display: block;
margin: 2px 0;
color: limegreen;
}
.usage code:first-child {
padding-top: 10px;
}
p {
margin: 15px 0;
}
.public p:first-child, .public pre.plaintext {
margin-top: 12px;
}
.doc {
margin: 0 0 26px 0;
clear: both;
}
.public .doc {
margin: 0;
}
.namespace-index .doc {
margin-bottom: 20px;
}
.namespace-index .namespace .doc {
margin-bottom: 10px;
}
.markdown p, .markdown li, .markdown dt, .markdown dd, .markdown td {
line-height: 22px;
}
.markdown li {
padding: 2px 0;
}
.markdown h2 {
font-weight: normal;
font-size: 25px;
margin: 30px 0 10px 0;
}
.markdown h3 {
font-weight: normal;
font-size: 20px;
margin: 30px 0 0 0;
}
.markdown h4 {
font-size: 15px;
margin: 22px 0 -4px 0;
}
.doc, .public, .namespace .index {
max-width: 680px;
overflow-x: visible;
}
.markdown pre > code {
display: block;
padding: 10px;
}
.markdown pre > code, .src-link a {
border: 1px solid lime;
border-radius: 2px;
}
.markdown code:not(.hljs), .src-link a {
background: #111;
}
pre.deps {
display: inline-block;
margin: 0 10px;
border: 1px solid lime;
border-radius: 2px;
padding: 10px;
background-color: #111;
}
.markdown hr {
border-style: solid;
border-top: none;
color: goldenrod;
}
.doc ul, .doc ol {
padding-left: 30px;
}
.doc table {
border-collapse: collapse;
margin: 0 10px;
}
.doc table td, .doc table th {
border: 1px solid goldenrod;
padding: 4px 6px;
}
.doc table th {
background: #111;
}
.doc dl {
margin: 0 10px 20px 10px;
}
.doc dl dt {
font-weight: bold;
margin: 0;
padding: 3px 0;
border-bottom: 1px solid goldenrod;
}
.doc dl dd {
padding: 5px 0;
margin: 0 0 5px 10px;
}
.doc abbr {
border-bottom: 1px dotted goldenrod;
font-variant: none;
cursor: help;
}
.src-link {
margin-bottom: 15px;
}
.src-link a {
font-size: 70%;
padding: 1px 4px;
text-decoration: none;
color: lime5bb;
}

View file

@ -1,97 +0,0 @@
/*
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
}
.hljs-comment,
.hljs-quote {
color: #998;
font-style: italic;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-subst {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-literal,
.hljs-variable,
.hljs-template-variable,
.hljs-tag .hljs-attr {
color: #008080;
}
.hljs-string,
.hljs-doctag {
color: #d14;
}
.hljs-title,
.hljs-section,
.hljs-selector-id {
color: #900;
font-weight: bold;
}
.hljs-subst {
font-weight: normal;
}
.hljs-type,
.hljs-class .hljs-title {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-name,
.hljs-attribute {
color: #000080;
font-weight: normal;
}
.hljs-regexp,
.hljs-link {
color: #009926;
}
.hljs-symbol,
.hljs-bullet {
color: #990073;
}
.hljs-built_in,
.hljs-builtin-name {
color: #0086b3;
}
.hljs-meta {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

View file

@ -1,11 +0,0 @@
{:resources ["css/default.css" "css/highlight.css"]
:transforms [[:head] [:append
[:link {:rel "stylesheet"
:type "text/css"
:href "css/default.css"}]
[:link {:rel "stylesheet"
:type "text/css"
:href "css/highlight.css"}]
[:link {:rel "icon"
:type "image/x-icon"
:href "../img/beowulf_logo_favicon.png"}]]]}

View file

@ -0,0 +1 @@
{:resources ["css/default.css" "css/highlight.css"]}

View file

@ -25,7 +25,6 @@
(T (ASSOC X (CDR L))))) (T (ASSOC X (CDR L)))))
SUBR (BEOWULF HOST ASSOC)) SUBR (BEOWULF HOST ASSOC))
(ATOM 32767 SUBR (BEOWULF HOST ATOM)) (ATOM 32767 SUBR (BEOWULF HOST ATOM))
(ATTRIB 32767 SUBR (BEOWULF HOST ATTRIB))
(CAR 32767 SUBR (BEOWULF HOST CAR)) (CAR 32767 SUBR (BEOWULF HOST CAR))
(CAAAAR 32767 EXPR (LAMBDA (X) (CAR (CAR (CAR (CAR X)))))) (CAAAAR 32767 EXPR (LAMBDA (X) (CAR (CAR (CAR (CAR X))))))
(CAAADR 32767 EXPR (LAMBDA (X) (CAR (CAR (CAR (CDR X)))))) (CAAADR 32767 EXPR (LAMBDA (X) (CAR (CAR (CAR (CDR X))))))
@ -56,16 +55,6 @@
(CDDDR 32767 EXPR (LAMBDA (X) (CDR (CDR (CDR X))))) (CDDDR 32767 EXPR (LAMBDA (X) (CDR (CDR (CDR X)))))
(CDDR 32767 EXPR (LAMBDA (X) (CDR (CDR X)))) (CDDR 32767 EXPR (LAMBDA (X) (CDR (CDR X))))
(CDR 32767 SUBR (BEOWULF HOST CDR)) (CDR 32767 SUBR (BEOWULF HOST CDR))
(CONC
32767
FEXPR
(LABEL
ARGS
(COND
((COND
((ONEP (LENGTH ARGS)) ARGS)
(T (ATTRIB (CAR ARGS) (APPLY CONC (CDR ARGS) NIL))))
ARGS))))
(CONS 32767 SUBR (BEOWULF HOST CONS)) (CONS 32767 SUBR (BEOWULF HOST CONS))
(CONSP 32767 SUBR (BEOWULF HOST CONSP)) (CONSP 32767 SUBR (BEOWULF HOST CONSP))
(COPY (COPY
@ -181,7 +170,6 @@
(COND (COND
((NULL X) (U)) ((NULL X) (U))
((EQ (CAR X) Y) (CDR X)) (T (PROP (CDR X) Y U))))) ((EQ (CAR X) Y) (CDR X)) (T (PROP (CDR X) Y U)))))
(PUT 32767 SUBR (BEOWULF HOST PUT))
(QUOTE 32767 EXPR (LAMBDA (X) X)) (QUOTE 32767 EXPR (LAMBDA (X) X))
(QUOTIENT 32767 SUBR (BEOWULF HOST QUOTIENT)) (QUOTIENT 32767 SUBR (BEOWULF HOST QUOTIENT))
(RANGE (RANGE
@ -199,7 +187,6 @@
(LAMBDA (N X) (COND ((EQ N 0) NIL) (T (CONS X (REPEAT (SUB1 N) X)))))) (LAMBDA (N X) (COND ((EQ N 0) NIL) (T (CONS X (REPEAT (SUB1 N) X))))))
(RPLACA 32767 SUBR (BEOWULF HOST RPLACA)) (RPLACA 32767 SUBR (BEOWULF HOST RPLACA))
(RPLACD 32767 SUBR (BEOWULF HOST RPLACD)) (RPLACD 32767 SUBR (BEOWULF HOST RPLACD))
(SASSOC 32767 SUBR (BEOWULF BOOTSTRAP SASSOC))
(SEARCH 32767 EXPR (SEARCH 32767 EXPR
(LAMBDA (X P F U) (LAMBDA (X P F U)
(COND ((NULL X) (U X)) (COND ((NULL X) (U X))

View file

@ -1,7 +1 @@
;; This isn't working but it's really not far off. ;; TODO
(PUT 'CONC 'FEXPR
;; possibly ARGS should be (ARGS)...
'(LABEL ARGS
(COND ((COND ((ONEP (LENGTH ARGS)) ARGS)
(T (ATTRIB (CAR ARGS) (APPLY CONC (CDR ARGS) NIL)))) ARGS))))

View file

@ -1,22 +0,0 @@
;; Common Lisp
(defun range (max &key (min 0) (step 1))
(loop for n from min below max by step
collect n))
(mapcar #'(lambda (x) (+ x 1)) (range 10))
(defun factoriali (n)
(reduce #'* (range (+ n 1) :min 1 :step 1)))
(defun factorialr (n)
(cond ((= n 1) 1)
(t (* n (factorialr (- n 1))))))
;; Clojure
(defn factorial [n]
(reduce *' (range 1 (+ n 1))))
(defn expt [n x]
(reduce *' (repeat x n)))

View file

@ -1,13 +0,0 @@
;; Bottom of page 66
(PUT 'SELECT 'FEXPR
'(LABEL FORM
(PROG (Q BODY)
(SETQ Q (EVAL (CAR FORM))) ;; not sure that Q should be evaled.
(SETQ BODY (CDR FORM))
LOOP
(COND
((EQ NIL (CDR BODY)) (RETURN (CAR BODY)))
((EQ Q (EVAL (CAAR BODY))) (RETURN (CDAR BODY))))
(SETQ BODY (CDR BODY))
(GO LOOP))))

View file

@ -11,11 +11,9 @@
objects." objects."
(:require [beowulf.cons-cell :refer [F make-beowulf-list make-cons-cell (:require [beowulf.cons-cell :refer [F make-beowulf-list make-cons-cell
pretty-print T]] pretty-print T]]
[beowulf.host :refer [ASSOC ATOM CAAR CAADR CADAR CADDR CADR CAR CDR [beowulf.host :refer [ASSOC ATOM CAAR CADAR CADDR CADR CAR CDR GET
CONS ERROR GET LIST NUMBERP PAIRLIS traced?]] LIST NUMBERP PAIRLIS traced?]]
[beowulf.oblist :refer [*options* NIL]] [beowulf.oblist :refer [*options* NIL oblist]])
[clojure.string :as s]
[clojure.tools.trace :refer [deftrace]])
(:import [beowulf.cons_cell ConsCell] (:import [beowulf.cons_cell ConsCell]
[clojure.lang Symbol])) [clojure.lang Symbol]))
@ -39,20 +37,10 @@
;;; ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(declare APPLY EVAL EVCON prog-eval) (declare APPLY EVAL prog-eval)
;;;; The PROGram feature ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; The PROGram feature ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def ^:dynamic
*depth*
"Stack depth. Unfortunately we need to be able to pass round depth for
functions which call EVAL/APPLY but do not know about depth."
0)
(defn- trace-indent
([] (trace-indent *depth*))
([d] (s/join (repeat d " "))))
(def find-target (def find-target
(memoize (memoize
(fn [target body] (fn [target body]
@ -94,45 +82,30 @@
(cond (cond
(number? expr) expr (number? expr) expr
(symbol? expr) (@vars expr) (symbol? expr) (@vars expr)
(instance? ConsCell expr) (case (CAR expr) (instance? ConsCell expr) (case (.getCar expr)
COND (prog-cond (CDR expr) COND (prog-cond (.getCdr expr)
vars env depth) vars env depth)
GO (let [target (CADR expr)] GO (make-cons-cell
(when (traced? 'PROG) '*PROGGO* (.getCar (.getCdr expr)))
(println " PROG:GO: Goto " target)) RETURN (make-cons-cell
(make-cons-cell
'*PROGGO* target))
RETURN (let [val (prog-eval
(CADR expr)
vars env depth)]
(when (traced? 'PROG)
(println " PROG:RETURN: Returning "
val))
(make-cons-cell
'*PROGRETURN* '*PROGRETURN*
val)) (prog-eval (.getCar (.getCdr expr))
SET (let [var (prog-eval (CADR expr) vars env depth))
vars env depth) SET (let [v (CADDR expr)]
val (prog-eval (CADDR expr)
vars env depth)]
(when (traced? 'PROG)
(println " PROG:SET: Setting "
var " to " val))
(swap! vars (swap! vars
assoc assoc
var (prog-eval (CADR expr)
val) vars env depth)
val) (prog-eval (CADDR expr)
SETQ (let [var (CADDR expr) vars env depth))
val (prog-eval var v)
vars env depth)] SETQ (let [v (CADDR expr)]
(when (traced? 'PROG)
(println " PROG:SETQ: Setting " var " to " val))
(swap! vars (swap! vars
assoc assoc
(CADR expr) (CADR expr)
val) (prog-eval v
val) vars env depth))
v)
;; else ;; else
(beowulf.bootstrap/EVAL expr (beowulf.bootstrap/EVAL expr
(merge-vars vars env) (merge-vars vars env)
@ -200,7 +173,7 @@
(println "Program:") (println "Program:")
(pretty-print program))) ;; for debugging (pretty-print program))) ;; for debugging
(loop [cursor body] (loop [cursor body]
(let [step (if (= NIL cursor) NIL (.getCar cursor))] (let [step (.getCar cursor)]
(when trace (do (println "Executing step: " step) (when trace (do (println "Executing step: " step)
(println " with vars: " @vars))) (println " with vars: " @vars)))
(cond (= cursor NIL) NIL (cond (= cursor NIL) NIL
@ -233,7 +206,7 @@
with these `args` at this depth." with these `args` at this depth."
[function-symbol args depth] [function-symbol args depth]
(when (traced? function-symbol) (when (traced? function-symbol)
(let [indent (trace-indent depth)] (let [indent (apply str (repeat depth "-"))]
(println (str indent "> " function-symbol " " args))))) (println (str indent "> " function-symbol " " args)))))
(defn- trace-response (defn- trace-response
@ -241,13 +214,11 @@
`function-symbol` at this depth." `function-symbol` at this depth."
[function-symbol response depth] [function-symbol response depth]
(when (traced? function-symbol) (when (traced? function-symbol)
(let [indent (apply str (trace-indent depth))] (let [indent (apply str (repeat depth "-"))]
(println (str "<" indent " " function-symbol " " response)))) (println (str "<" indent " " function-symbol " " response))))
response) response)
;;;; Support functions for interpreter ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn- value
(defn value
"Seek a value for this symbol `s` by checking each of these indicators in "Seek a value for this symbol `s` by checking each of these indicators in
turn." turn."
([s] ([s]
@ -257,21 +228,6 @@
(first (remove #(= % NIL) (map #(GET s %) (first (remove #(= % NIL) (map #(GET s %)
indicators)))))) indicators))))))
(defn SASSOC
"Like `ASSOC`, but with an action to take if no value is found.
From the manual, page 60:
'The function `sassoc` searches `y`, which is a list of dotted pairs, for
a pair whose first element that is `x`. If such a pair is found, the value
of `sassoc` is this pair. Otherwise the function `u` of no arguments is
taken as the value of `sassoc`.'"
[x y u]
(let [v (ASSOC x y)]
(if-not (= v NIL) v
(APPLY u NIL NIL))))
;;;; APPLY ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; APPLY ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn try-resolve-subroutine (defn try-resolve-subroutine
@ -292,7 +248,7 @@
return the result." return the result."
[^Symbol function-symbol args ^ConsCell environment depth] [^Symbol function-symbol args ^ConsCell environment depth]
(trace-call function-symbol args depth) (trace-call function-symbol args depth)
(let [lisp-fn (value function-symbol '(EXPR FEXPR)) ;; <-- should these be handled differently? I think so! (let [lisp-fn (value function-symbol '(EXPR FEXPR))
args' (cond (= NIL args) args args' (cond (= NIL args) args
(empty? args) NIL (empty? args) NIL
(instance? ConsCell args) args (instance? ConsCell args) args
@ -319,43 +275,6 @@
(trace-response function-symbol result depth) (trace-response function-symbol result depth)
result)) result))
;; (LABEL ARGS
;; (COND ((COND ((ONEP (LENGTH ARGS)) ARGS)
;; (T (ATTRIB (CAR ARGS) (APPLY CONC (CDR ARGS) NIL))))
;; ARGS)))
;; ((1 2 3 4) (5 6 7 8) (9 10 11 12))
;; NIL
;; (def function (make-beowulf-list '(LABEL ARGS (COND
;; ((COND ((ONEP (LENGTH ARGS)) ARGS)
;; (T (ATTRIB (CAR ARGS)
;; (APPLY CONC (CDR ARGS) NIL))))
;; ARGS)))))
;; (def args (make-beowulf-list '((1 2 3 4) (5 6 7 8) (9 10 11 12))))
;; function
;; (CADR function)
;; (CADDR function)
(defn apply-label
"Apply in the special case that the first element in the function is `LABEL`."
[function args environment depth]
(EVAL
(CADDR function)
(CONS
(CONS (CADR function) args)
environment)
depth))
;; (apply-label function args NIL 1)
;; (APPLY function args NIL 1)
(defn- apply-lambda
"Apply in the special case that the first element in the function is `LAMBDA`."
[function args environment depth]
(EVAL
(CADDR function)
(PAIRLIS (CADR function) args environment) depth))
(defn APPLY (defn APPLY
"Apply this `function` to these `arguments` in this `environment` and return "Apply this `function` to these `arguments` in this `environment` and return
the result. the result.
@ -363,10 +282,7 @@
For bootstrapping, at least, a version of APPLY written in Clojure. For bootstrapping, at least, a version of APPLY written in Clojure.
All args are assumed to be symbols or `beowulf.cons-cell/ConsCell` objects. All args are assumed to be symbols or `beowulf.cons-cell/ConsCell` objects.
See page 13 of the Lisp 1.5 Programmers Manual." See page 13 of the Lisp 1.5 Programmers Manual."
([function args environment] [function args environment depth]
(APPLY function args environment *depth*))
([function args environment depth]
(binding [*depth* (inc depth)]
(trace-call 'APPLY (list function args environment) depth) (trace-call 'APPLY (list function args environment) depth)
(let [result (cond (let [result (cond
(= NIL function) (if (:strict *options*) (= NIL function) (if (:strict *options*)
@ -378,19 +294,26 @@
:type :beowulf}))) :type :beowulf})))
(= (ATOM function) T) (apply-symbolic function args environment (inc depth)) (= (ATOM function) T) (apply-symbolic function args environment (inc depth))
:else (case (first function) :else (case (first function)
LABEL (apply-label function args environment depth) LABEL (APPLY
(CADDR function)
args
(make-cons-cell
(make-cons-cell
(CADR function)
(CADDR function))
environment)
depth)
FUNARG (APPLY (CADR function) args (CADDR function) depth) FUNARG (APPLY (CADR function) args (CADDR function) depth)
LAMBDA (apply-lambda function args environment depth) LAMBDA (EVAL
;; else (CADDR function)
;; OK, this is *not* what is says in the manual... (PAIRLIS (CADR function) args environment) depth)
;; COND (EVCON ???)
(throw (ex-info "Ungecnáwen wyrþan sí þegnung-weard" (throw (ex-info "Ungecnáwen wyrþan sí þegnung-weard"
{:phase :apply {:phase :apply
:function function :function function
:args args :args args
:type :beowulf}))))] :type :beowulf}))))]
(trace-response 'APPLY result depth) (trace-response 'APPLY result depth)
result)))) result))
;;;; EVAL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; EVAL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -438,12 +361,12 @@
(println (str indent ": EVAL: sceald bindele: " (or v "nil")))) (println (str indent ": EVAL: sceald bindele: " (or v "nil"))))
(if (instance? ConsCell v) (if (instance? ConsCell v)
(.getCdr v) (.getCdr v)
(let [v' (value expr)] (let [v' (value expr (list 'APVAL))]
(when (traced? 'EVAL) (when (traced? 'EVAL)
(println (str indent ": EVAL: deóp bindele: (" expr " . " (or v' "nil") ")"))) (println (str indent ": EVAL: deóp bindele: (" expr " . " (or v' "nil") ")")))
(if v' (if v'
v' v'
(throw (ex-info (format "Ne tácen-bindele āfand: `%s`" expr) (throw (ex-info "Ne tácen-bindele āfand"
{:phase :eval {:phase :eval
:function 'EVAL :function 'EVAL
:args (list expr env depth) :args (list expr env depth)
@ -489,10 +412,11 @@
(EVLIS (CDR expr) env depth) (EVLIS (CDR expr) env depth)
env env
depth)) depth))
:else (EVAL (CONS (CDR (SASSOC (CAR expr) env (fn [] (ERROR 'A9)))) :else (APPLY
(CDR expr)) (CAR expr)
(EVLIS (CDR expr) env depth)
env env
(inc depth)))] depth))]
(trace-response 'EVAL result depth) (trace-response 'EVAL result depth)
result))) result)))

View file

@ -53,8 +53,7 @@
(.canRead (io/file %))) (.canRead (io/file %)))
"Could not find sysout file"]] "Could not find sysout file"]]
["-s" "--strict" "Strictly interpret the Lisp 1.5 language, without extensions."] ["-s" "--strict" "Strictly interpret the Lisp 1.5 language, without extensions."]
["-t" "--time" "Time evaluations."] ["-t" "--time" "Time evaluations."]])
["-x" "--testing" "Disable the jline reader - useful when piping input."]])
(defn- re (defn- re
"Like REPL, but it isn't a loop and doesn't print." "Like REPL, but it isn't a loop and doesn't print."
@ -65,9 +64,10 @@
"Read/eval/print loop." "Read/eval/print loop."
[prompt] [prompt]
(loop [] (loop []
(print prompt)
(flush) (flush)
(try (try
(if-let [input (trim (read-from-console prompt))] (if-let [input (trim (read-from-console))]
(if (= input stop-word) (if (= input stop-word)
(throw (ex-info "\nFærwell!" {:cause :quit})) (throw (ex-info "\nFærwell!" {:cause :quit}))
(println (println
@ -116,7 +116,7 @@
(catch Throwable any (catch Throwable any
(println any)))) (println any))))
(try (try
(repl (:prompt (:options args))) (repl (str (:prompt (:options args)) " "))
(catch (catch
Exception Exception
e e

View file

@ -91,21 +91,22 @@
(cond (cond
(= l NIL) NIL (= l NIL) NIL
(empty? path) l (empty? path) l
(not (instance? ConsCell l)) (throw (ex-info (str "Ne liste: " :else
l "; " (type l)) (try
{:phase :eval (case (last path)
:function "universal access function"
:args [l path]
:type :beowulf}))
:else (case (last path)
\a (uaf (.first l) (butlast path)) \a (uaf (.first l) (butlast path))
\d (uaf (.getCdr l) (butlast path)) \d (uaf (.getCdr l) (butlast path))
(throw (ex-info (str "uaf: unexpected letter in path (only `a` and `d` permitted): " (throw (ex-info (str "uaf: unexpected letter in path (only `a` and `d` permitted): " (last path))
(last path)) {:cause :uaf
{:phase :eval :detail :unexpected-letter
:function "universal access function" :expr (last path)})))
:args [l path] (catch ClassCastException e
:type :beowulf}))))) (throw (ex-info
(str "uaf: Not a LISP list? " (type l))
{:cause :uaf
:detail :not-a-lisp-list
:expr l}
e))))))
(defmacro CAAR [x] `(uaf ~x '(\a \a))) (defmacro CAAR [x] `(uaf ~x '(\a \a)))
(defmacro CADR [x] `(uaf ~x '(\a \d))) (defmacro CADR [x] `(uaf ~x '(\a \d)))
@ -216,7 +217,7 @@
:phase :host :phase :host
:detail :rplacd :detail :rplacd
:args (list cell value) :args (list cell value)
:type :beowulf})))) :type :beowulf}))));; PLUS
(defn LIST (defn LIST
[& args] [& args]
@ -432,41 +433,6 @@
"The unexplained magic number which marks the start of a property list." "The unexplained magic number which marks the start of a property list."
(Integer/parseInt "77777" 8)) (Integer/parseInt "77777" 8))
(defn hit-or-miss-assoc
"Find the position of the binding of this `target` in a Lisp 1.5
property list `plist`.
Lisp 1.5 property lists are not assoc lists, but lists of the form
`(name value name value name value...)`. It's therefore necessary to
recurse down the list two entries at a time to avoid confusing names
with values."
[target plist]
(if (and (instance? ConsCell plist) (even? (count plist)))
(cond (= plist NIL) NIL
(= (first plist) target) plist
:else (hit-or-miss-assoc target (CDDR plist)))
NIL))
(defn ATTRIB
"Destructive append. From page 59 of the manual:
The function `attrib` concatenates its two arguments by changing the last
element of its first argument to point to the second argument. Thus it
is commonly used to tack something onto the end of a property list.
The value of `attrib` is the second argument.
For example
```
attrib[FF; (EXPR (LAMBDA (X) (COND ((ATOM X) X) (T (FF (CAR x))))))]
```
would put EXPR followed by the LAMBDA expression for FF onto the end of
the property list for FF."
[x e]
(loop [l x]
(cond
(instance? ConsCell (CDR l)) (recur (CDR l))
:else (when (RPLACD l e) e))))
(defn PUT (defn PUT
"Put this `value` as the value of the property indicated by this `indicator` "Put this `value` as the value of the property indicated by this `indicator`
of this `symbol`. Return `value` on success. of this `symbol`. Return `value` on success.
@ -474,19 +440,15 @@
NOTE THAT there is no `PUT` defined in the manual, but it would have been NOTE THAT there is no `PUT` defined in the manual, but it would have been
easy to have defined it so I don't think this fully counts as an extension." easy to have defined it so I don't think this fully counts as an extension."
[symbol indicator value] [symbol indicator value]
(let [binding (ASSOC symbol @oblist)] (if-let [binding (ASSOC symbol @oblist)]
(if (instance? ConsCell binding) (if-let [prop (ASSOC indicator (CDDR binding))]
(let [prop (hit-or-miss-assoc indicator (CDDR binding))] (RPLACD prop value)
(if (instance? ConsCell prop)
(RPLACA (CDR prop) value)
;; The implication is ATTRIB was used here, but I have not made that
;; work and this does work, so if it ain't broke don't fix it.
(RPLACD binding (RPLACD binding
(make-cons-cell (make-cons-cell
magic-marker magic-marker
(make-cons-cell (make-cons-cell
indicator indicator
(make-cons-cell value (CDDR binding))))))) (make-cons-cell value (CDDR binding))))))
(swap! (swap!
oblist oblist
(fn [ob s p v] (fn [ob s p v]
@ -494,7 +456,6 @@
(make-beowulf-list (list s magic-marker p v)) (make-beowulf-list (list s magic-marker p v))
ob)) ob))
symbol indicator value))) symbol indicator value)))
value)
(defn GET (defn GET
"From the manual: "From the manual:
@ -516,9 +477,13 @@
val (cond val (cond
(= binding NIL) NIL (= binding NIL) NIL
(= magic-marker (= magic-marker
(CADR binding)) (let [p (hit-or-miss-assoc indicator binding)] (CADR binding)) (loop [b binding]
(if-not (= NIL p) ;; (println "GET loop, seeking " indicator ":")
(CADR p) ;; (pretty-print b)
(if (instance? ConsCell b)
(if (= (CAR b) indicator)
(CADR b) ;; <- this is what we should actually be returning
(recur (CDR b)))
NIL)) NIL))
:else (throw :else (throw
(ex-info "Misformatted property list (missing magic marker)" (ex-info "Misformatted property list (missing magic marker)"
@ -534,10 +499,9 @@
`indicator` of the symbol which is the first element of the pair to the `indicator` of the symbol which is the first element of the pair to the
value which is the second element of the pair. See page 58 of the manual." value which is the second element of the pair. See page 58 of the manual."
[a-list indicator] [a-list indicator]
(doall
(map (map
#(when (PUT (CAR %) indicator (CDR %)) (CAR %)) #(PUT (CAR %) indicator (CDR %))
a-list))) a-list))
(defn DEFINE (defn DEFINE
"Bootstrap-only version of `DEFINE` which, post boostrap, can be overwritten "Bootstrap-only version of `DEFINE` which, post boostrap, can be overwritten

View file

@ -91,8 +91,7 @@
([] ([]
(SYSOUT nil)) (SYSOUT nil))
([filepath] ([filepath]
(let [destination (full-path (str filepath))] (spit (full-path (str filepath))
(spit destination
(with-out-str (with-out-str
(println (apply str (repeat 79 ";"))) (println (apply str (repeat 79 ";")))
(println (format ";; Beowulf %s Sysout file generated at %s" (println (format ";; Beowulf %s Sysout file generated at %s"
@ -104,9 +103,7 @@
(println) (println)
(let [output (safely-wrap-subrs @oblist)] (let [output (safely-wrap-subrs @oblist)]
(pretty-print output) (pretty-print output)
))) )))))
(println "Saved sysout to " destination)
NIL)))
(defn resolve-subr (defn resolve-subr
"If this oblist `entry` references a subroutine, attempt to fix up that "If this oblist `entry` references a subroutine, attempt to fix up that

View file

@ -41,5 +41,5 @@
(def ^:dynamic *options* (def ^:dynamic *options*
"Command line options from invocation." "Command line options from invocation."
{:testing true}) {})

View file

@ -13,14 +13,13 @@
Both these extensions can be disabled by using the `--strict` command line Both these extensions can be disabled by using the `--strict` command line
switch." switch."
(:require [beowulf.oblist :refer [*options*]] (:require ;; [beowulf.reader.char-reader :refer [read-chars]]
[beowulf.reader.char-reader :refer [read-chars]]
[beowulf.reader.generate :refer [generate]] [beowulf.reader.generate :refer [generate]]
[beowulf.reader.parser :refer [parse]] [beowulf.reader.parser :refer [parse]]
[beowulf.reader.simplify :refer [simplify]] [beowulf.reader.simplify :refer [simplify]]
[clojure.string :refer [join split starts-with? trim]]) [clojure.string :refer [join split starts-with? trim]])
(:import [instaparse.gll Failure] (:import [java.io InputStream]
[java.io InputStream])) [instaparse.gll Failure]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; ;;;
@ -83,35 +82,24 @@
(throw (ex-info "Ne can forstande " (assoc parse-tree :source source)))) (throw (ex-info "Ne can forstande " (assoc parse-tree :source source))))
(generate (simplify parse-tree))))) (generate (simplify parse-tree)))))
(defn- dummy-read-chars [prompt] (defn read-from-console
(loop [r "" p prompt] "Attempt to read a complete lisp expression from the console. NOTE that this
(if (and (seq r) will only really work for S-Expressions, not M-Expressions."
(= (count (re-seq #"\(" r)) []
(loop [r (read-line)]
(if (and (= (count (re-seq #"\(" r))
(count (re-seq #"\)" r))) (count (re-seq #"\)" r)))
(= (count (re-seq #"\[" r)) (= (count (re-seq #"\[" r))
(count (re-seq #"\]" r)))) (count (re-seq #"\]" r))))
r r
(do (recur (str r "\n" (read-line))))))
(print (str p " "))
(flush)
(recur (str r "\n" (read-line)) "::")))))
(defn read-from-console
"Attempt to read a complete lisp expression from the console.
There's a major problem here that the read-chars reader messes up testing.
We need to be able to disable it while testing!"
[prompt]
(if (:testing *options*)
(dummy-read-chars prompt)
(read-chars prompt)))
(defn READ (defn READ
"An implementation of a Lisp reader sufficient for bootstrapping; not necessarily "An implementation of a Lisp reader sufficient for bootstrapping; not necessarily
the final Lisp reader. `input` should be either a string representation of a LISP the final Lisp reader. `input` should be either a string representation of a LISP
expression, or else an input stream. A single form will be read." expression, or else an input stream. A single form will be read."
([] ([]
(gsp (read-from-console (:prompt *options*)))) (gsp (read-from-console)))
([input] ([input]
(cond (cond
(empty? input) (READ) (empty? input) (READ)

View file

@ -20,12 +20,9 @@
TODO: There are multiple problems with JLine; a better solution might be TODO: There are multiple problems with JLine; a better solution might be
to start from here: to start from here:
https://stackoverflow.com/questions/7931988/how-to-manipulate-control-characters" https://stackoverflow.com/questions/7931988/how-to-manipulate-control-characters"
(:require [beowulf.oblist :refer [*options* oblist]]) ;; (:import [org.jline.reader LineReader LineReaderBuilder]
(:import [org.jline.reader.impl.completer StringsCompleter] ;; [org.jline.terminal TerminalBuilder])
[org.jline.reader.impl DefaultParser DefaultParser$Bracket] )
[org.jline.reader LineReaderBuilder]
[org.jline.terminal TerminalBuilder]
[org.jline.widget AutopairWidgets AutosuggestionWidgets]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; ;;;
@ -52,56 +49,27 @@
;; looks as though you'd need a DPhil in JLine to write it, and I don't have ;; looks as though you'd need a DPhil in JLine to write it, and I don't have
;; the time. ;; the time.
(defn build-completer ;; (def get-reader
"Build a completer which takes tokens from the oblist. ;; "Return a reader, first constructing it if necessary.
This is sort-of working, in as much as hitting <TAB> on a blank line will ;; **NOTE THAT** this is not settled API. The existence and call signature of
show a table of values from the oblist, but hitting <TAB> after you've ;; this function is not guaranteed in future versions."
started input does not show potential completions for tokens you've started." ;; (memoize (fn []
[] ;; (let [term (.build (.system (TerminalBuilder/builder) true))]
(StringsCompleter. (map #(str (first %)) @oblist))) ;; (.build (.terminal (LineReaderBuilder/builder) term))))))
;; This breaks; it is not correctly resolving the Enum, although I can't work out ;; (defn read-chars
;; why not. ;; "A drop-in replacement for `clojure.core/read-line`, except that line editing
;; (defn build-parser ;; and history should be enabled.
;; **NOTE THAT** this does not work yet, but it is in the API because I hope
;; that it will work later!"
;; [] ;; []
;; (println "Building parser") ;; (let [eddie (get-reader)]
;; (let [parser (DefaultParser.)] ;; (loop [s (.readLine eddie)]
;; (doall ;; (if (and (= (count (re-seq #"\(" s))
;; (.setEofOnUnclosedBracket ;; (count (re-seq #"\)" s)))
;; parser DefaultParser$Bracket/ROUND)))) ;; (= (count (re-seq #"\[]" s))
;; (count (re-seq #"\]" s))))
(def get-reader ;; s
"Return a reader, first constructing it if necessary. ;; (recur (str s " " (.readLine eddie)))))))
**NOTE THAT** this is not settled API. The existence and call signature of
this function is not guaranteed in future versions."
(memoize (fn []
(let [term (.build (.system (TerminalBuilder/builder) true))
reader (-> (LineReaderBuilder/builder)
(.terminal term)
(.completer (build-completer))
;; #(.parser % (build-parser))
(.build))
;; apw (AutopairWidgets. reader false)
;; asw (AutosuggestionWidgets. reader)
]
;; (.enable apw)
;; (.enable asw)
reader))))
(defn read-chars
"A drop-in replacement for `clojure.core/read-line`, except that line editing
and history should be enabled.
**NOTE THAT** this does not fully work yet, but it is in the API because I
hope that it will work later!"
[prompt]
(let [eddie (get-reader)]
(loop [s (.readLine eddie (str prompt " "))]
(if (and (= (count (re-seq #"\(" s))
(count (re-seq #"\)" s)))
(= (count (re-seq #"\[]" s))
(count (re-seq #"\]" s))))
s
(recur (str s " " (.readLine eddie ":: ")))))))

View file

@ -1,9 +1,8 @@
(ns beowulf.core-test (ns beowulf.core-test
(:require [beowulf.core :refer [-main repl stop-word]] (:require [clojure.java.io :refer [reader]]
[beowulf.oblist :refer [*options*]] [clojure.string :refer [split]]
[clojure.java.io :refer [reader]] [clojure.test :refer [deftest is testing]]
[clojure.string :refer [split starts-with?]] [beowulf.core :refer [-main repl stop-word]]))
[clojure.test :refer [deftest is testing]]))
;; (deftest a-test ;; (deftest a-test
;; (testing "FIXME, I fail." ;; (testing "FIXME, I fail."
@ -21,20 +20,20 @@
(deftest repl-tests (deftest repl-tests
(testing "quit functionality" (testing "quit functionality"
(with-open [r (reader (string->stream stop-word))] (with-open [r (reader (string->stream stop-word))]
(binding [clojure.core/*in* r (binding [*in* r]
*options* (assoc *options* :testing true)]
(is (thrown-with-msg? Exception #"\nFærwell!" (repl ""))))) (is (thrown-with-msg? Exception #"\nFærwell!" (repl "")))))
(let [expected nil (let [expected nil
actual (with-open [r (reader (string->stream stop-word))] actual (with-open [r (reader (string->stream stop-word))]
(binding [*in* r] (binding [*in* r]
(-main "--testing")))] (-main)))]
(is (= actual expected))))) (is (= actual expected)))))
;; The new read-chars interface is really messing with this. Need to sort out! ;; TODO: not working because STOP is not being recognised, but I haven't
;; OK, binding `:testing` doesn't work because `*options*` gets rebound in main. ;; worked out why not yet. It *did* work.
;; Need to be able to pass in a testing flag as argument to -main
(deftest flag-tests (deftest flag-tests
(testing "Only testing flag" (testing "No flags"
(let [expected-greeting "Hider wilcuman. Béowulf is mín nama." (let [expected-greeting "Hider wilcuman. Béowulf is mín nama."
expected-quit-message (str "Sprecan '" stop-word "' tó laéfan") expected-quit-message (str "Sprecan '" stop-word "' tó laéfan")
expected-result #".*\(3 \. 4\)" expected-result #".*\(3 \. 4\)"
@ -42,22 +41,24 @@
expected-signoff "Færwell!" expected-signoff "Færwell!"
;; anticipated output (note blank lines): ;; anticipated output (note blank lines):
;; Hider wilcuman. Béowulf is mín nama. ; Hider wilcuman. Béowulf is mín nama.
;; Sprecan 'STOP' tó laéfan ; Sprecan 'STOP' tó laéfan
;; Sprecan:: > (3 . 4) ; Sprecan:: > (3 . 4)
;; Sprecan:: ; Sprecan::
;; Færwell! ; Færwell!
[_ greeting _ _ quit-message _ result prompt signoff] [_ greeting _ _ quit-message _ result prompt signoff]
(with-open [r (reader (string->stream (str "cons[3; 4]\n" stop-word)))] (with-open [r (reader (string->stream (str "cons[3; 4]\n" stop-word)))]
(binding [*in* r] (binding [*in* r]
(split (with-out-str (-main "--testing")) #"\n")))] (split (with-out-str (-main)) #"\n")))]
(is (= greeting expected-greeting)) (is (= greeting expected-greeting))
; (is (= error expected-error))
(is (re-matches expected-result result)) (is (re-matches expected-result result))
(is (= quit-message expected-quit-message)) (is (= quit-message expected-quit-message))
(is (= prompt expected-prompt)) (is (= prompt expected-prompt))
(is (= signoff expected-signoff)))) (is (= signoff expected-signoff))
))
(testing "unknown flag" (testing "unknown flag"
(let [expected-greeting "Hider wilcuman. Béowulf is mín nama." (let [expected-greeting "Hider wilcuman. Béowulf is mín nama."
expected-quit-message (str "Sprecan '" stop-word "' tó laéfan") expected-quit-message (str "Sprecan '" stop-word "' tó laéfan")
@ -68,63 +69,115 @@
[_ greeting _ error quit-message _ result prompt signoff] [_ greeting _ error quit-message _ result prompt signoff]
(with-open [r (reader (string->stream (str "cons[5; 6]\n" stop-word)))] (with-open [r (reader (string->stream (str "cons[5; 6]\n" stop-word)))]
(binding [*in* r] (binding [*in* r]
(split (with-out-str (-main "--unknown" "--testing")) #"\n")))] (split (with-out-str (-main "--unknown")) #"\n")))]
(is (= greeting expected-greeting)) (is (= greeting expected-greeting))
(is (re-matches expected-error error)) (is (re-matches expected-error error))
(is (re-matches expected-result result)) (is (re-matches expected-result result))
(is (= quit-message expected-quit-message)) (is (= quit-message expected-quit-message))
(is (= prompt expected-prompt)) (is (= prompt expected-prompt))
(is (= signoff expected-signoff)))) (is (= signoff expected-signoff))
;; ;; TODO: not working because STOP is not being recognised, but I haven't ))
;; ;; worked out why not yet. It *did* work. ; (testing "help"
; (let [expected-greeting "Hider wilcuman. Béowulf is mín nama."
;; Hider wilcuman. Béowulf is mín nama. ; expected-h1 " -h, --help"
;; -f FILEPATH, --file-path FILEPATH Set the path to the directory for reading and writing Lisp files. ; expected-quit-message (str "Sprecan '" stop-word "' tó laéfan")
;; -h, --help ; expected-result #".*\(A \. B\)"
;; -p PROMPT, --prompt PROMPT Sprecan:: Set the REPL prompt to PROMPT ; expected-prompt "Sprecan:: "
;; -r SYSOUTFILE, --read SYSOUTFILE lisp1.5.lsp Read Lisp system from file SYSOUTFILE ; expected-signoff "Færwell!"
;; -s, --strict Strictly interpret the Lisp 1.5 language, without extensions. ; [_ greeting _ h1 _ _ _ _ quit-message _ result prompt signoff]
;; -t, --time Time evaluations. ; (with-open [r (reader (string->stream (str "cons[A; B]\n" stop-word)))]
;; -x, --testing Disable the jline reader - useful when piping input. ; (binding [*in* r]
;; Sprecan 'STOP' tó laéfan ; (split (with-out-str (-main "--help")) #"\n")))]
; (is (= greeting expected-greeting))
;; Sprecan:: ; (is (= h1 expected-h1))
; (is (re-matches expected-result result))
(testing "help" ; (is (= quit-message expected-quit-message))
(let [expected-greeting "Hider wilcuman. Béowulf is mín nama." ; (is (= prompt expected-prompt))
expected-h1 " -h, --help" ; (is (= signoff expected-signoff))
expected-quit-message (str "Sprecan '" stop-word "' tó laéfan") ; ))
expected-result #".*\(A \. B\)" ; (testing "prompt"
expected-prompt "Sprecan:: " ; (let [expected-greeting "Hider wilcuman. Béowulf is mín nama."
expected-signoff "Færwell!" ; expected-quit-message (str "Sprecan '" stop-word "' tó laéfan")
[_ greeting _ _ h1 _ _ _ _ _ quit-message _ result prompt signoff] ; expected-error ""
(with-open [r (reader (string->stream (str "cons[A; B]\n" stop-word)))] ; expected-result #".*\(A \. B\).*"
(binding [*in* r] ; expected-prompt "? "
(split (with-out-str (-main "--help" "--testing")) #"\n")))] ; expected-signoff "Færwell!"
(is (= greeting expected-greeting)) ; [_ greeting _ error quit-message _ result prompt signoff]
(is (= h1 expected-h1)) ; (with-open [r (reader (string->stream (str stop-word)))]
(is (re-matches expected-result result)) ; (binding [*in* r]
(is (= quit-message expected-quit-message)) ; (split (with-out-str (-main "--prompt" "?")) #"\n")))]
(is (starts-with? prompt expected-prompt)) ; (is (= greeting expected-greeting))
(is (= signoff expected-signoff)))) ; (is (= error expected-error))
(testing "prompt" ; (is (re-matches expected-result result ))
(let [expected-prompt "? " ; (is (= quit-message expected-quit-message))
[_ _ _ _ _ _ prompt _] ; (is (= prompt expected-prompt))
(with-open [r (reader (string->stream stop-word))] ; (is (= signoff expected-signoff))
(binding [*in* r] ; ))
(split (with-out-str (-main "--prompt" "?" "--testing")) #"\n")))] ; (testing "read - file not found"
(is (= prompt expected-prompt)))) ; (let [expected-greeting "Hider wilcuman. Béowulf is mín nama."
(testing "read - file not found" ; expected-quit-message (str "Sprecan '" stop-word "' tó laéfan")
(let [expected-error #"Failed to validate.*" ; expected-error #"Failed to validate.*"
[_ _ _ error _ _ _ _ _] ; expected-result #".*\(A \. B\)"
(with-open [r (reader (string->stream (str "cons[A; B]\n" stop-word)))] ; expected-prompt "Sprecan:: "
(binding [*in* r] ; expected-signoff "Færwell!"
(split (with-out-str (-main "--testing" "--read" "froboz")) #"\n")))] ; [_ greeting _ error quit-message _ result prompt signoff]
(is (re-matches expected-error error)))) ; (with-open [r (reader (string->stream (str "cons[A; B]\n" stop-word)))]
(testing "strict" ; (binding [*in* r]
(let [expected-result #".*Cannot parse meta expressions in strict mode.*" ; (split (with-out-str (-main "--read" "froboz")) #"\n")))]
[_ _ _ _ _ _ result _ _] ; (is (= greeting expected-greeting))
(with-open [r (reader (string->stream (str "cons[A; B]\n" stop-word)))] ; (is (re-matches expected-error error))
(binding [*in* r] ; (is (re-matches expected-result result))
(split (with-out-str (-main "--strict" "--testing")) #"\n")))] ; (is (= quit-message expected-quit-message))
(is (re-matches expected-result result ))))) ; (is (= prompt expected-prompt))
; (is (= signoff expected-signoff))
; ))
; (testing "read - file found"
; ;; TODO: there's no feedback from this because the initfile
; ;; is not yet read. This will change
; (let [expected-greeting "Hider wilcuman. Béowulf is mín nama."
; expected-quit-message (str "Sprecan '" stop-word "' tó laéfan")
; expected-error ""
; expected-result #".*\(A \. B\)"
; expected-prompt "Sprecan:: "
; expected-signoff "Færwell!"
; [_ greeting error quit-message _ _ result prompt signoff]
; (with-open [r (reader (string->stream (str "cons[A; B]\n" stop-word)))]
; (binding [*in* r]
; (split (with-out-str (-main "--read" "README.md")) #"\n")))]
; (is (= greeting expected-greeting))
; (is (= error expected-error))
; (is (re-matches expected-result result))
; (is (= quit-message expected-quit-message))
; (is (= prompt expected-prompt))
; (is (= signoff expected-signoff))
; ))
; (testing "strict"
; (let [expected-greeting "Hider wilcuman. Béowulf is mín nama."
; expected-quit-message (str "Sprecan '" stop-word "' tó laéfan")
; expected-error ""
; expected-result #".*Cannot parse meta expressions in strict mode.*"
; expected-prompt "Sprecan:: "
; expected-signoff "Færwell!"
; [_ greeting _ error quit-message _ result prompt signoff]
; (with-open [r (reader (string->stream (str "cons[A; B]\n" stop-word)))]
; (binding [*in* r]
; (split (with-out-str (-main "--strict")) #"\n")))]
; (is (= greeting expected-greeting))
; (is (= error expected-error))
; (is (re-matches expected-result result ))
; (is (= quit-message expected-quit-message))
; (is (= prompt expected-prompt))
; (is (= signoff expected-signoff))
; ))
; ; (testing "trace"
; (let [expected-greeting "Hider wilcuman. Béowulf is mín nama."
; expected-error ""
; expected-trace #".*traced-eval.*"
; [_ greeting _ error _ _ trace & _]
; (with-open [r (reader (string->stream (str "cons[A; B]\n" stop-word)))]
; (binding [*in* r]
; (split (with-out-str (-main "--trace")) #"\n")))]
; (is (= greeting expected-greeting))
; (is (= error expected-error))
; (is (re-matches expected-trace trace))
)

View file

@ -1,24 +1,9 @@
(ns beowulf.host-test (ns beowulf.host-test
(:require [beowulf.cons-cell :refer [F make-beowulf-list make-cons-cell T]] (:require [clojure.test :refer [deftest is testing]]
[beowulf.host :refer [ADD1 AND CADDDR CAR CDR DEFINE DIFFERENCE [beowulf.cons-cell :refer [F make-beowulf-list T]]
ERROR FIXP GREATERP lax? LESSP NILP NULL [beowulf.host :refer [CDR DIFFERENCE NUMBERP PLUS RPLACA RPLACD TIMES]]
NUMBERP OR PLUS RPLACA RPLACD SUB1 TIMES uaf]] [beowulf.oblist :refer [NIL]]
[beowulf.io :refer [SYSIN]] [beowulf.read :refer [gsp]]))
[beowulf.oblist :refer [*options* NIL]]
[beowulf.read :refer [gsp]]
[clojure.test :refer [deftest is testing use-fixtures]]
[expectations.clojure.test
:refer [defexpect expect more-> more-of]]))
(use-fixtures :once (fn [f]
(try (when (SYSIN "resources/lisp1.5.lsp")
(f))
(catch Throwable any
(throw (ex-info "Failed to load Lisp sysout"
{:phase test
:function 'SYSIN
:file "resources/lisp1.5.lsp"}
any))))))
(deftest destructive-change-test (deftest destructive-change-test
(testing "RPLACA" (testing "RPLACA"
@ -37,30 +22,17 @@
Exception Exception
#"Uncynlic miercels in RPLACA.*" #"Uncynlic miercels in RPLACA.*"
(RPLACA '(A B C D E) 'F)) (RPLACA '(A B C D E) 'F))
"You can't RPLACA into anything which isn't a MutableSequence.")) "You can't RPLACA into anything which isn't a MutableSequence.")
(testing "RPLACD" )
(testing "RPLACA"
(let (let
[l (make-beowulf-list '(A B C D E)) [l (make-beowulf-list '(A B C D E))
target (CDR l) target (CDR l)
expected "(A B . F)" expected "(A B . F)"
actual (do (RPLACD target 'F) (print-str l))] actual (do (RPLACD target 'F) (print-str l))]
(is (= actual expected))) (is (= actual expected)))
(let )
[l (make-beowulf-list '(A B C D E)) )
target (CDR l)
expected "(A B)"
actual (do (RPLACD target NIL) (print-str l))]
(is (= actual expected)))
(is (thrown-with-msg?
Exception
#"Un-ġefōg þing in RPLACD.*"
(RPLACD (make-beowulf-list '(A B C D E)) :a))
"You can't represent a keyword in Lisp 1.5")
(is (thrown-with-msg?
Exception
#"Uncynlic miercels in RPLACD.*"
(RPLACD "ABCDE" 'F))
"You can't RPLACD into anything which isn't a MutableSequence.")))
(deftest numberp-tests (deftest numberp-tests
(testing "NUMBERP" (testing "NUMBERP"
@ -87,171 +59,12 @@
(let [expected 3.5 (let [expected 3.5
actual (PLUS 1.25 9/4)] actual (PLUS 1.25 9/4)]
(is (= actual expected)) (is (= actual expected))
(is (float? actual)))
(let [expected 3.5
actual (PLUS -2.5 6)]
(is (= actual expected) "Negative numbers are cool.")
(is (float? actual)))) (is (float? actual))))
(testing "TIMES" (testing "TIMES"
(let [expected 6 (let [expected 6
actual (TIMES 2 3)] actual (TIMES 2 3)]
(is (= actual expected)))
(let [expected 2.5
actual (TIMES 5 0.5)]
(is (= actual expected)))) (is (= actual expected))))
(testing "DIFFERENCE" (testing DIFFERENCE
(let [expected -1 (let [expected -1
actual (DIFFERENCE 1 2)] actual (DIFFERENCE 1 2)]
(is (= actual expected)))
(let [expected (float 0.1)
actual (DIFFERENCE -0.1 -0.2)]
(is (= actual expected))))
(testing "ADD1"
(let [expected -1
actual (ADD1 -2)]
(is (= actual expected)))
(let [expected (float 3.5)
actual (ADD1 2.5)]
(is (= actual expected))))
(testing "SUB1"
(let [expected -3
actual (SUB1 -2)]
(is (= actual expected)))
(let [expected (float 1.5)
actual (SUB1 2.5)]
(is (= actual expected))))) (is (= actual expected)))))
(deftest laxness
(testing "lax"
(let [expected true
actual (lax? 'Test)]
(is (= actual expected) "Pass, the Queen's Cat, and all's well")))
(testing "strict"
(binding [*options* (assoc *options* :strict true)]
(is (thrown-with-msg? Exception #".*ne āfand innan Lisp 1.5" (lax? 'Test))))))
(deftest access-tests
(testing "primitive access"
(let [cell (make-cons-cell 1 7)]
(let [expected 1
actual (CAR cell)]
(is (= actual expected)))
(let [expected 7
actual (CDR cell)]
(is (= actual expected))))
(is (thrown-with-msg? Exception #".*Ne can tace CAR of.*" (CAR 7)))
(is (thrown-with-msg? Exception #".*Ne can tace CDR of.*" (CDR 'A)))
(is (thrown-with-msg? Exception #".*Ne liste.*" (CADDDR "Foo")))
(is (thrown-with-msg? Exception #".*uaf: unexpected letter in path.*"
(uaf (make-beowulf-list '(A B C D))
'(\d \a \z \e \d))))))
(deftest misc-predicate-tests
(testing "NULL"
(let [expected T
actual (NULL NIL)]
(is (= actual expected)))
(let [expected F
actual (NULL (make-beowulf-list '(A B C)))]
(is (= actual expected))))
(testing "NILP"
(let [expected T
actual (NILP NIL)]
(is (= actual expected)))
(let [expected NIL
actual (NILP (make-beowulf-list '(A B C)))]
(is (= actual expected))))
(testing "AND"
(let [expected T
actual (AND)]
(is (= actual expected)))
(let [expected T
actual (AND T T)]
(is (= actual expected)))
(let [expected T
actual (AND T T T)]
(is (= actual expected)))
(let [expected T
actual (AND 1 'A (make-beowulf-list '(A B C)))]
(is (= actual expected)))
(let [expected F
actual (AND NIL)]
(is (= actual expected)))
(let [expected F
actual (AND T T F T)]
(is (= actual expected))))
(testing "OR"
(let [expected F
actual (OR)]
(is (= actual expected)))
(let [expected T
actual (OR NIL T)]
(is (= actual expected)))
(let [expected T
actual (OR T F T)]
(is (= actual expected)))
(let [expected T
actual (OR 1 F (make-beowulf-list '(A B C)))]
(is (= actual expected)))
(let [expected F
actual (OR NIL)]
(is (= actual expected)))
(let [expected F
actual (OR NIL F)]
(is (= actual expected))))
(testing "FIXP"
(let [expected F
actual (FIXP NIL)]
(is (= actual expected)))
(let [expected F
actual (FIXP 'A)]
(is (= actual expected)))
(let [expected F
actual (FIXP 3.2)]
(is (= actual expected)))
(let [expected T
actual (FIXP 7)]
(is (= actual expected))))
(testing "LESSP"
(let [expected F
actual (LESSP 7 3)]
(is (= actual expected)))
(let [expected T
actual (LESSP -7 3.5)]
(is (= actual expected)))
(let [expected F
actual (LESSP 3.14 3.14)]
(is (= actual expected))))
(testing "GREATERP"
(let [expected T
actual (GREATERP 7 3)]
(is (= actual expected)))
(let [expected F
actual (GREATERP -7 3.5)]
(is (= actual expected)))
(let [expected F
actual (GREATERP 3.14 3.14)]
(is (= actual expected)))))
;; Really tricky to get DEFINE set up for testing here. It works OK in the
;; REPL, but there's nonsense going on with lazy sequences. Better to
;; reimplement in Lisp.
;; (deftest define-tests
;; (testing "DEFINE"
;; (let [expected "(FF)"
;; actual (str (doall (DEFINE
;; (gsp "((FF LAMBDA (X) (COND ((ATOM X) X) (T (FF (CAR X))))))"))))]
;; (is (= actual expected)))))
(defexpect error-without-code
(expect (more-> clojure.lang.ExceptionInfo type
(more-of {:keys [:phase :function :args :type :code]}
'A1 code) ex-data)
(ERROR)))
(defexpect error-with-code
(let [x 'X1]
(expect (more-> clojure.lang.ExceptionInfo type
(more-of {:keys [:phase :function :args :type :code]}
x code) ex-data)
(ERROR x))))

View file

@ -1,13 +1,13 @@
(ns beowulf.lisp-test (ns beowulf.lisp-test
"The idea here is to test actual Lisp functions" "The idea here is to test actual Lisp functions"
(:require [beowulf.bootstrap :refer [EVAL]] (:require [clojure.test :refer [deftest testing is use-fixtures]]
[beowulf.bootstrap :refer [EVAL]]
[beowulf.cons-cell :refer [make-beowulf-list]] [beowulf.cons-cell :refer [make-beowulf-list]]
[beowulf.io :refer [SYSIN]] ;; [beowulf.oblist :refer [NIL]] [beowulf.io :refer [SYSIN]]
[beowulf.oblist :refer [NIL]] ;; [beowulf.oblist :refer [NIL]]
[beowulf.read :refer [READ]] [beowulf.read :refer [READ]]))
[clojure.test :refer [deftest is testing use-fixtures]]))
(defn reps (defn- reps
"'Read eval print string', or 'read eval print single'. "'Read eval print string', or 'read eval print single'.
Reads and evaluates one input string, and returns the Reads and evaluates one input string, and returns the
output string." output string."
@ -130,6 +130,7 @@
actual (reps input)] actual (reps input)]
(is (= actual expected)))))) (is (= actual expected))))))
(deftest MEMBER-tests (deftest MEMBER-tests
(testing "member" (testing "member"
(let [expected "T" (let [expected "T"
@ -146,18 +147,17 @@
(is (= actual expected))))) (is (= actual expected)))))
;; This is failing, and although yes, it does matter, I have not yet tracked the reason. ;; This is failing, and although yes, it does matter, I have not yet tracked the reason.
(deftest sublis-tests ;; (deftest sublis-tests
(testing "sublis" ;; (testing "sublis"
(let [expected "(SHAKESPEARE WROTE (THE TEMPEST))" ;; (let [expected "(SHAKESPEARE WROTE (THE TEMPEST))"
actual (reps ;; actual (reps
"(SUBLIS ;; "(SUBLIS
'((X . SHAKESPEARE) (Y . (THE TEMPEST))) ;; '((X . SHAKESPEARE) (Y . (THE TEMPEST)))
'(X WROTE Y))")] ;; '(X WROTE Y))")]
(is (= actual expected))))) ;; (is (= actual expected)))))
(deftest prog-tests (deftest prog-tests
(testing "PROG" (testing "PROG"
;; (reps "(TRACE 'PROG)")
(let [expected "5" (let [expected "5"
actual (reps "(PROG (X) actual (reps "(PROG (X)
(SETQ X 1) (SETQ X 1)
@ -166,60 +166,3 @@
(COND ((EQ X 5) (RETURN X)) (COND ((EQ X 5) (RETURN X))
(T (GO START))))")] (T (GO START))))")]
(is (= actual expected))))) (is (= actual expected)))))
(deftest put-get-tests
(let [symbol 'TESTSYMBOL
p1 'TESTPROPONE
p2 'TESTPROPTWO]
(testing "GET - property should be missing"
(let [expected "NIL"
actual (reps "(GET 'TESTSYMBOL 'TESTPROPONE)")]
(is (= actual expected))))
(testing "PUT and GET: value of new property; change value of property"
(let [prop (reps "(GENSYM)")
val1 (reps "(GENSYM)")
val2 (reps "(GENSYM)")
expected1 val1
actual1 (when (reps (str "(PUT '" symbol " '" prop " '" val1 ")"))
(reps (str "(GET '" symbol " '" prop ")")))
expected2 val2
actual2 (when (reps (str "(PUT '" symbol " '" prop " '" val2 ")"))
(reps (str "(GET '" symbol " '" prop ")")))]
(is (not= val1 val2))
(is (= actual1 expected1) "The value set can be retrieved.")
(is (= actual2 expected2) "The value is changed.")))
(testing "PUT and GET: different properties have independent values"
(let [val1 (reps "(GENSYM)")
val2 (reps "(GENSYM)")
expected1 val1
actual1 (when (reps (str "(PUT '" symbol " '" p1 " '" val1 ")"))
(reps (str "(GET '" symbol " '" p1 ")")))
expected2 val2
actual2 (when (reps (str "(PUT '" symbol " '" p2 " '" val2 ")"))
(reps (str "(GET '" symbol " '" p2 ")")))
expected3 val1
actual3 (reps (str "(GET '" symbol " '" p1 ")"))]
(is (not= val1 val2))
(is (= actual1 expected1) "The value set can be retrieved.")
(is (= actual2 expected2) "Values are independent.")
(is (= actual3 expected3) "Setting a second property does not obliterate the first.")))))
(deftest fsubr-tests
(testing "FSUBR/CONC"
(reps "(SETQ P (RANGE 1 4))")
(reps "(SETQ Q (RANGE 5 8))")
(reps "(SETQ R (RANGE 9 12))")
(let [expected "(1 2 3 4 5 6 7 8 9 10 11 12)"
actual (reps "(CONC P Q R)")]
(is (= actual expected)))))
(deftest attrib-tests
(testing "ATTRIB"
(reps "(SETQ X '(A B C))")
(reps "(SETQ Y '(D E F))")
(let [expected "(D E F)"
actual (reps "(ATTRIB X Y)")]
(is (= actual expected)))
(let [expected "(A B C D E F)"
actual (reps "X")]
(is (= actual expected)))))