diff --git a/README.md b/README.md
index 364cfe3..430ce62 100644
--- a/README.md
+++ b/README.md
@@ -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
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.
+same behaviour — except as documented below.
### BUT WHY?!!?!
@@ -62,14 +62,11 @@ Working Lisp interpreter, but some key features not yet implemented.
### 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
-educational and archaeological project, not serious engineering.
+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.
-Some `readline`-like functionality would be really useful, but my attempt to
-integrate [JLine](https://github.com/jline/jline3) has not (yet) been successful.
+Some `readline`-like functionality would be really useful, but my attempt to 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
-implement one.
+An in-core structure editor would be an extremely nice thing, and I may well implement one.
You are of course welcome to fork the project and do whatever you like with it!
@@ -110,53 +107,53 @@ now be possible to reimplement them as `FEXPRs` and so the reader macro function
| Function | Type | Signature | Implementation | Documentation |
|--------------|----------------|------------------|----------------|----------------------|
-| NIL | Lisp variable | ? | | see manual pages 22, 69 |
-| T | Lisp variable | ? | | see manual pages 22, 69 |
-| F | Lisp variable | ? | | see manual pages 22, 69 |
-| ADD1 | Host lambda function | ? | | ? |
-| 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. |
-| APPEND | Lisp lambda function | ? | | see manual pages 11, 61 |
-| 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. |
-| 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. |
-| 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`. |
-| 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. |
-| CAAAAR | Lisp lambda function | ? | ? | ? |
-| CAAADR | Lisp lambda function | ? | ? | ? |
-| CAAAR | Lisp lambda function | ? | ? | ? |
-| CAADAR | Lisp lambda function | ? | ? | ? |
-| CAADDR | Lisp lambda function | ? | ? | ? |
-| CAADR | Lisp lambda function | ? | ? | ? |
-| CAAR | Lisp lambda function | ? | ? | ? |
-| CADAAR | Lisp lambda function | ? | ? | ? |
-| CADADR | Lisp lambda function | ? | ? | ? |
-| CADAR | Lisp lambda function | ? | ? | ? |
-| CADDAR | Lisp lambda function | ? | ? | ? |
-| CADDDR | Lisp lambda function | ? | ? | ? |
-| CADDR | Lisp lambda function | ? | ? | ? |
-| CADR | Lisp lambda function | ? | ? | ? |
-| CDAAAR | Lisp lambda function | ? | ? | ? |
-| CDAADR | Lisp lambda function | ? | ? | ? |
-| CDAAR | Lisp lambda function | ? | ? | ? |
-| CDADAR | Lisp lambda function | ? | ? | ? |
-| CDADDR | Lisp lambda function | ? | ? | ? |
-| CDADR | Lisp lambda function | ? | ? | ? |
-| CDAR | Lisp lambda function | ? | ? | ? |
-| CDDAAR | Lisp lambda function | ? | ? | ? |
-| CDDADR | Lisp lambda function | ? | ? | ? |
-| CDDAR | Lisp lambda function | ? | ? | ? |
-| CDDDAR | Lisp lambda function | ? | ? | ? |
-| CDDDDR | Lisp lambda function | ? | ? | ? |
-| CDDDR | Lisp lambda function | ? | ? | ? |
-| CDDR | Lisp lambda function | ? | ? | ? |
-| 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. |
-| CONS | Host lambda function | ? | | 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. |
-| COPY | Lisp lambda function | ? | | see manual pages 62 |
-| 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. |
-| DIFFERENCE | Host lambda function | ? | | ? |
-| DIVIDE | Lisp lambda function | ? | | see manual pages 26, 64 |
-| 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. |
-| EFFACE | Lisp lambda function | ? | PSEUDO-FUNCTION | see manual pages 63 |
+| NIL | Lisp variable | ? | | The canonical empty list. See manual pages 22, 69s |
+| T | Lisp variable | ? | | The canonical true value. See manual pages 22, 69 |
+| F | Lisp variable | ? | | The canonical false value. See manual pages 22, 69 |
+| ADD1 | Host lambda function | x:number | | Add one to the number `x`. |
+| AND | Host lambda function | expr* | 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. |
+| APPEND | Lisp lambda function | ? | | see manual pages 11, 61 |
+| 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. |
+| 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 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. |
+| 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 | 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 | list | ? | ? |
+| CAAADR | Lisp lambda function | list | ? | ? |
+| CAAAR | Lisp lambda function | list | ? | ? |
+| CAADAR | Lisp lambda function | list | ? | ? |
+| CAADDR | Lisp lambda function | list | ? | ? |
+| CAADR | Lisp lambda function | list | ? | ? |
+| CAAR | Lisp lambda function | list | ? | ? |
+| CADAAR | Lisp lambda function | list | ? | ? |
+| CADADR | Lisp lambda function | list | ? | ? |
+| CADAR | Lisp lambda function | list | ? | ? |
+| CADDAR | Lisp lambda function | list | ? | ? |
+| CADDDR | Lisp lambda function | list | ? | ? |
+| CADDR | Lisp lambda function | list | ? | ? |
+| CADR | Lisp lambda function | list | ? | ? |
+| CDAAAR | Lisp lambda function | list | ? | ? |
+| CDAADR | Lisp lambda function | list | ? | ? |
+| CDAAR | Lisp lambda function | list | ? | ? |
+| CDADAR | Lisp lambda function | list | ? | ? |
+| CDADDR | Lisp lambda function | list | ? | ? |
+| CDADR | Lisp lambda function | list | ? | ? |
+| CDAR | Lisp lambda function | list | ? | ? |
+| CDDAAR | Lisp lambda function | list | ? | ? |
+| CDDADR | Lisp lambda function | list | ? | ? |
+| CDDAR | Lisp lambda function | list | ? | ? |
+| CDDDAR | Lisp lambda function | list | ? | ? |
+| CDDDDR | Lisp lambda function | list | ? | ? |
+| CDDDR | Lisp lambda function | list | ? | ? |
+| CDDR | Lisp lambda function | list | ? | ? |
+| 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 | expr, expr | | Construct a new instance of cons cell with this `car` and `cdr`. |
+| CONSP | Host lambda function | o:expr | ? | Return `T` if object `o` is a cons cell, else `F`.
**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 62 |
+| 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. |
+| DIFFERENCE | Host lambda function | x:number, y:number | | Returns the result of subtracting the number `y` from the number `x` |
+| DIVIDE | Lisp lambda function | x:number, y:number | | see manual pages 26, 64 |
+| 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. |
+| EFFACE | Lisp lambda function | ? | PSEUDO-FUNCTION | see manual pages 63 |
| 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`. |
| 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 | ? | ? | ? |
| FIXP | Host lambda function | ? | PREDICATE | ? |
| 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.'
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. |
| GREATERP | Host lambda function | ? | PREDICATE | ? |
| INTEROP | Host lambda function | ? | ? | ? |
| INTERSECTION | Lisp lambda function | ? | ? | ? |
-| LENGTH | Lisp lambda function | ? | | see manual pages 62 |
+| LENGTH | Lisp lambda function | ? | | see manual pages 62 |
| LESSP | Host lambda function | ? | PREDICATE | ? |
-| MAPLIST | Lisp lambda function | ? | FUNCTIONAL | see manual pages 20, 21, 63 |
-| MEMBER | Lisp lambda function | ? | PREDICATE | see manual pages 11, 62 |
-| MINUSP | Lisp lambda function | ? | PREDICATE | see manual pages 26, 64 |
-| NOT | Lisp lambda function | ? | PREDICATE | see manual pages 21, 23, 58 |
-| NULL | Lisp lambda function | ? | PREDICATE | see manual pages 11, 57 |
+| MAPLIST | Lisp lambda function | ? | FUNCTIONAL | see manual pages 20, 21, 63 |
+| MEMBER | Lisp lambda function | ? | PREDICATE | see manual pages 11, 62 |
+| MINUSP | Lisp lambda function | ? | PREDICATE | see manual pages 26, 64 |
+| NOT | Lisp lambda function | ? | PREDICATE | see manual pages 21, 23, 58 |
+| NULL | Lisp lambda function | ? | PREDICATE | see manual pages 11, 57 |
| 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. |
-| ONEP | Lisp lambda function | ? | PREDICATE | see manual pages 26, 64 |
-| 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. |
-| PAIR | Lisp lambda function | ? | | see manual pages 60 |
-| 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. |
+| 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. |
+| ONEP | Lisp lambda function | ? | PREDICATE | see manual pages 26, 64 |
+| 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. |
+| PAIR | Lisp lambda function | ? | | see manual pages 60 |
+| 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.
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. |
| PLUS | Host lambda function | ? | | ? |
| PRETTY | | ? | ? | ? |
-| PRINT | | ? | PSEUDO-FUNCTION | see manual pages 65, 84 |
-| 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. |
-| PROP | Lisp lambda function | ? | FUNCTIONAL | see manual pages 59 |
-| QUOTE | Lisp lambda function | ? | | see manual pages 10, 22, 71 |
-| 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. |
+| PRINT | | ? | PSEUDO-FUNCTION | see manual pages 65, 84 |
+| 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. |
+| PROP | Lisp lambda function | ? | FUNCTIONAL | see manual pages 59 |
+| QUOTE | Lisp lambda function | ? | | see manual pages 10, 22, 71 |
+| 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 | ? | ? | ? |
| 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 | ? | | ? |
| 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) |
-| 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 63 |
-| 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! |
+| 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) |
+| SEARCH | Lisp lambda function | ? | FUNCTIONAL | see manual pages 63 |
+| 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! |
| SUB1 | Lisp lambda function, Host lambda function | ? | | ? |
| SUB2 | Lisp lambda function | ? | ? | ? |
-| SUBLIS | Lisp lambda function | ? | | see manual pages 12, 61 |
-| SUBST | Lisp lambda function | ? | | see manual pages 11, 61 |
-| 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. |
-| 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. |
-| TERPRI | | ? | PSEUDO-FUNCTION | see manual pages 65, 84 |
+| SUBLIS | Lisp lambda function | ? | | see manual pages 12, 61 |
+| SUBST | Lisp lambda function | ? | | see manual pages 11, 61 |
+| 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. |
+| 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 strict mode. |
+| TERPRI | | ? | PSEUDO-FUNCTION | see manual pages 65, 84 |
| 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. |
| 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. |
-| ZEROP | Lisp lambda function | ? | PREDICATE | see manual pages 26, 64 |
+| 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 26, 64 |
Functions described as 'Lisp function' above are defined in the default
sysout file, `resources/lisp1.5.lsp`, which will be loaded by default unless
@@ -219,8 +216,7 @@ over the Clojure implementations.
### Architectural plan
-Not everything documented in this section is yet built. It indicates the
-direction of travel and intended destination, not the current state.
+Not everything documented in this section is yet built. It indicates the direction of travel and intended destination, not the current state.
#### resources/lisp1.5.lsp
diff --git a/doc/lisp1.5.md b/doc/lisp1.5.md
index 11fe6db..6042cc8 100644
--- a/doc/lisp1.5.md
+++ b/doc/lisp1.5.md
@@ -1721,7 +1721,6 @@ represented in storage only once,
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
one from the other is given in LISP.
-
We assume that we have a list of the form
n, = ((A B C) (D E F),... , (X Y z)),
@@ -2710,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.
For example
-```
-attrib[FF; (EXPR (LAMBDA (X) (COND ((ATOM X) X) (T (FF (CAR x))))))]
-```
+attrib[~~; (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-
erty list for FF.
diff --git a/docs/cloverage/beowulf/bootstrap.clj.html b/docs/cloverage/beowulf/bootstrap.clj.html
index 8a1fa87..c45387d 100644
--- a/docs/cloverage/beowulf/bootstrap.clj.html
+++ b/docs/cloverage/beowulf/bootstrap.clj.html
@@ -331,13 +331,13 @@
109 ;; else
-
+
110 (beowulf.bootstrap/EVAL expr
-
+
111 (merge-vars vars env)
-
+
112 depth))))
@@ -352,13 +352,13 @@
116
-
+
117 Lisp 1.5 introduced `PROG`, and most Lisps have been stuck with it ever
-
+
118 since. It introduces imperative programming into what should be a pure
-
+
119 functional language, and consequently it's going to be a pig to implement.
@@ -757,7 +757,7 @@
251 (let [lisp-fn (value function-symbol '(EXPR FEXPR))
-
+
252 args' (cond (= NIL args) args
diff --git a/docs/cloverage/beowulf/cons_cell.clj.html b/docs/cloverage/beowulf/cons_cell.clj.html
index aaf1230..a229691 100644
--- a/docs/cloverage/beowulf/cons_cell.clj.html
+++ b/docs/cloverage/beowulf/cons_cell.clj.html
@@ -259,7 +259,7 @@
085 (if
-
+
086 (or
@@ -445,22 +445,22 @@
147 clojure.lang.Counted
-
+
148 (count [this] (loop [cell this
149 result 1]
-
+
150 (if
-
+
151 (and (coll? (.getCdr cell)) (not= NIL (.getCdr cell)))
-
+
152 (recur (.getCdr cell) (inc result))
-
+
153 result)))
diff --git a/docs/cloverage/beowulf/core.clj.html b/docs/cloverage/beowulf/core.clj.html
index adf35d5..209aa59 100644
--- a/docs/cloverage/beowulf/core.clj.html
+++ b/docs/cloverage/beowulf/core.clj.html
@@ -154,10 +154,10 @@
050 :default default-sysout
-
+
051 :validate [#(and
-
+
052 (.exists (io/file %))
@@ -170,40 +170,40 @@
055 ["-s" "--strict" "Strictly interpret the Lisp 1.5 language, without extensions."]
- 056 ["-t" "--time" "Time evaluations."]
-
-
- 057 ["-x" "--testing" "Disable the jline reader - useful when piping input."]])
+ 056 ["-t" "--time" "Time evaluations."]])
- 058
+ 057
- 059 (defn- re
+ 058 (defn- re
- 060 "Like REPL, but it isn't a loop and doesn't print."
+ 059 "Like REPL, but it isn't a loop and doesn't print."
- 061 [input]
+ 060 [input]
- 062 (EVAL (READ input) NIL 0))
+ 061 (EVAL (READ input) NIL 0))
- 063
+ 062
- 064 (defn repl
+ 063 (defn repl
- 065 "Read/eval/print loop."
+ 064 "Read/eval/print loop."
- 066 [prompt]
+ 065 [prompt]
- 067 (loop []
+ 066 (loop []
+
+
+ 067 (print prompt)
068 (flush)
@@ -211,8 +211,8 @@
069 (try
-
- 070 (if-let [input (trim (read-from-console prompt))]
+
+ 070 (if-let [input (trim (read-from-console))]
071 (if (= input stop-word)
@@ -259,7 +259,7 @@
085 data
-
+
086 (case (:cause data)
@@ -316,13 +316,13 @@
104 (str "Síðe " (System/getProperty "beowulf.version") "\n"))
-
+
105 (when
106 (:help (:options args))
-
+
107 (:summary args))
@@ -358,8 +358,8 @@
118 (try
-
- 119 (repl (:prompt (:options args)))
+
+ 119 (repl (str (:prompt (:options args)) " "))
120 (catch
diff --git a/docs/cloverage/beowulf/host.clj.html b/docs/cloverage/beowulf/host.clj.html
index e11a000..5a4bbed 100644
--- a/docs/cloverage/beowulf/host.clj.html
+++ b/docs/cloverage/beowulf/host.clj.html
@@ -130,19 +130,19 @@
042 [symbol]
-
+
043 (when (:strict *options*)
-
+
044 (throw (ex-info (format "%s ne āfand innan Lisp 1.5" symbol)
-
+
045 {:type :strict
046 :phase :host
-
+
047 :function symbol})))
@@ -274,7 +274,7 @@
090 [l path]
-
+
091 (cond
@@ -283,1493 +283,1439 @@
093 (empty? path) l
-
- 094 (not (instance? ConsCell l)) (throw (ex-info (str "Ne liste: "
-
-
- 095 l "; " (type l))
-
-
- 096 {:phase :eval
-
- 097 :function "universal access function"
+ 094 :else
-
- 098 :args [l path]
-
-
- 099 :type :beowulf}))
+
+ 095 (try
- 100 :else (case (last path)
+ 096 (case (last path)
- 101 \a (uaf (.first l) (butlast path))
+ 097 \a (uaf (.first l) (butlast path))
- 102 \d (uaf (.getCdr l) (butlast path))
+ 098 \d (uaf (.getCdr l) (butlast path))
-
- 103 (throw (ex-info (str "uaf: unexpected letter in path (only `a` and `d` permitted): "
+
+ 099 (throw (ex-info (str "uaf: unexpected letter in path (only `a` and `d` permitted): " (last path))
-
- 104 (last path))
-
-
- 105 {:phase :eval
+
+ 100 {:cause :uaf
- 106 :function "universal access function"
+ 101 :detail :unexpected-letter
-
- 107 :args [l path]
+
+ 102 :expr (last path)})))
- 108 :type :beowulf})))))
+ 103 (catch ClassCastException e
+
+
+ 104 (throw (ex-info
+
+
+ 105 (str "uaf: Not a LISP list? " (type l))
+
+
+ 106 {:cause :uaf
+
+
+ 107 :detail :not-a-lisp-list
+
+
+ 108 :expr l}
+
+
+ 109 e))))))
- 109
+ 110
- 110 (defmacro CAAR [x] `(uaf ~x '(\a \a)))
+ 111 (defmacro CAAR [x] `(uaf ~x '(\a \a)))
- 111 (defmacro CADR [x] `(uaf ~x '(\a \d)))
+ 112 (defmacro CADR [x] `(uaf ~x '(\a \d)))
-
- 112 (defmacro CDDR [x] `(uaf ~x '(\d \d)))
+
+ 113 (defmacro CDDR [x] `(uaf ~x '(\d \d)))
- 113 (defmacro CDAR [x] `(uaf ~x '(\d \a)))
+ 114 (defmacro CDAR [x] `(uaf ~x '(\d \a)))
- 114
+ 115
- 115 (defmacro CAAAR [x] `(uaf ~x '(\a \a \a)))
+ 116 (defmacro CAAAR [x] `(uaf ~x '(\a \a \a)))
- 116 (defmacro CAADR [x] `(uaf ~x '(\a \a \d)))
+ 117 (defmacro CAADR [x] `(uaf ~x '(\a \a \d)))
- 117 (defmacro CADAR [x] `(uaf ~x '(\a \d \a)))
+ 118 (defmacro CADAR [x] `(uaf ~x '(\a \d \a)))
- 118 (defmacro CADDR [x] `(uaf ~x '(\a \d \d)))
+ 119 (defmacro CADDR [x] `(uaf ~x '(\a \d \d)))
- 119 (defmacro CDDAR [x] `(uaf ~x '(\d \d \a)))
+ 120 (defmacro CDDAR [x] `(uaf ~x '(\d \d \a)))
- 120 (defmacro CDDDR [x] `(uaf ~x '(\d \d \d)))
+ 121 (defmacro CDDDR [x] `(uaf ~x '(\d \d \d)))
- 121 (defmacro CDAAR [x] `(uaf ~x '(\d \a \a)))
+ 122 (defmacro CDAAR [x] `(uaf ~x '(\d \a \a)))
- 122 (defmacro CDADR [x] `(uaf ~x '(\d \a \d)))
+ 123 (defmacro CDADR [x] `(uaf ~x '(\d \a \d)))
- 123
+ 124
- 124 (defmacro CAAAAR [x] `(uaf ~x '(\a \a \a \a)))
+ 125 (defmacro CAAAAR [x] `(uaf ~x '(\a \a \a \a)))
- 125 (defmacro CAADAR [x] `(uaf ~x '(\a \a \d \a)))
+ 126 (defmacro CAADAR [x] `(uaf ~x '(\a \a \d \a)))
- 126 (defmacro CADAAR [x] `(uaf ~x '(\a \d \a \a)))
+ 127 (defmacro CADAAR [x] `(uaf ~x '(\a \d \a \a)))
- 127 (defmacro CADDAR [x] `(uaf ~x '(\a \d \d \a)))
+ 128 (defmacro CADDAR [x] `(uaf ~x '(\a \d \d \a)))
- 128 (defmacro CDDAAR [x] `(uaf ~x '(\d \d \a \a)))
+ 129 (defmacro CDDAAR [x] `(uaf ~x '(\d \d \a \a)))
- 129 (defmacro CDDDAR [x] `(uaf ~x '(\d \d \d \a)))
+ 130 (defmacro CDDDAR [x] `(uaf ~x '(\d \d \d \a)))
- 130 (defmacro CDAAAR [x] `(uaf ~x '(\d \a \a \a)))
+ 131 (defmacro CDAAAR [x] `(uaf ~x '(\d \a \a \a)))
- 131 (defmacro CDADAR [x] `(uaf ~x '(\d \a \d \a)))
+ 132 (defmacro CDADAR [x] `(uaf ~x '(\d \a \d \a)))
- 132 (defmacro CAAADR [x] `(uaf ~x '(\a \a \a \d)))
+ 133 (defmacro CAAADR [x] `(uaf ~x '(\a \a \a \d)))
- 133 (defmacro CAADDR [x] `(uaf ~x '(\a \a \d \d)))
+ 134 (defmacro CAADDR [x] `(uaf ~x '(\a \a \d \d)))
- 134 (defmacro CADADR [x] `(uaf ~x '(\a \d \a \d)))
+ 135 (defmacro CADADR [x] `(uaf ~x '(\a \d \a \d)))
- 135 (defmacro CADDDR [x] `(uaf ~x '(\a \d \d \d)))
+ 136 (defmacro CADDDR [x] `(uaf ~x '(\a \d \d \d)))
- 136 (defmacro CDDADR [x] `(uaf ~x '(\d \d \a \d)))
+ 137 (defmacro CDDADR [x] `(uaf ~x '(\d \d \a \d)))
- 137 (defmacro CDDDDR [x] `(uaf ~x '(\d \d \d \d)))
+ 138 (defmacro CDDDDR [x] `(uaf ~x '(\d \d \d \d)))
- 138 (defmacro CDAADR [x] `(uaf ~x '(\d \a \a \d)))
+ 139 (defmacro CDAADR [x] `(uaf ~x '(\d \a \a \d)))
- 139 (defmacro CDADDR [x] `(uaf ~x '(\d \a \d \d)))
+ 140 (defmacro CDADDR [x] `(uaf ~x '(\d \a \d \d)))
- 140
+ 141
- 141 (defn RPLACA
+ 142 (defn RPLACA
- 142 "Replace the CAR pointer of this `cell` with this `value`. Dangerous, should
+ 143 "Replace the CAR pointer of this `cell` with this `value`. Dangerous, should
- 143 really not exist, but does in Lisp 1.5 (and was important for some
+ 144 really not exist, but does in Lisp 1.5 (and was important for some
- 144 performance hacks in early Lisps)"
+ 145 performance hacks in early Lisps)"
- 145 [^ConsCell cell value]
+ 146 [^ConsCell cell value]
- 146 (if
+ 147 (if
- 147 (instance? ConsCell cell)
+ 148 (instance? ConsCell cell)
- 148 (if
+ 149 (if
- 149 (or
+ 150 (or
- 150 (instance? ConsCell value)
+ 151 (instance? ConsCell value)
- 151 (number? value)
+ 152 (number? value)
- 152 (symbol? value)
+ 153 (symbol? value)
- 153 (= value NIL))
+ 154 (= value NIL))
- 154 (try
+ 155 (try
- 155 (.rplaca cell value)
+ 156 (.rplaca cell value)
- 156 cell
+ 157 cell
- 157 (catch Throwable any
+ 158 (catch Throwable any
- 158 (throw (ex-info
+ 159 (throw (ex-info
- 159 (str (.getMessage any) " in RPLACA: `")
+ 160 (str (.getMessage any) " in RPLACA: `")
- 160 {:cause :upstream-error
+ 161 {:cause :upstream-error
- 161 :phase :host
+ 162 :phase :host
- 162 :function :rplaca
+ 163 :function :rplaca
- 163 :args (list cell value)
+ 164 :args (list cell value)
- 164 :type :beowulf}
+ 165 :type :beowulf}
- 165 any))))
+ 166 any))))
- 166 (throw (ex-info
+ 167 (throw (ex-info
- 167 (str "Un-ġefōg þing in RPLACA: `" value "` (" (type value) ")")
+ 168 (str "Un-ġefōg þing in RPLACA: `" value "` (" (type value) ")")
- 168 {:cause :bad-value
+ 169 {:cause :bad-value
- 169 :phase :host
+ 170 :phase :host
- 170 :function :rplaca
+ 171 :function :rplaca
- 171 :args (list cell value)
+ 172 :args (list cell value)
- 172 :type :beowulf})))
+ 173 :type :beowulf})))
- 173 (throw (ex-info
+ 174 (throw (ex-info
- 174 (str "Uncynlic miercels in RPLACA: `" cell "` (" (type cell) ")")
+ 175 (str "Uncynlic miercels in RPLACA: `" cell "` (" (type cell) ")")
- 175 {:cause :bad-cell
+ 176 {:cause :bad-cell
- 176 :phase :host
+ 177 :phase :host
- 177 :function :rplaca
+ 178 :function :rplaca
- 178 :args (list cell value)
+ 179 :args (list cell value)
- 179 :type :beowulf}))))
+ 180 :type :beowulf}))))
- 180
+ 181
- 181 (defn RPLACD
+ 182 (defn RPLACD
- 182 "Replace the CDR pointer of this `cell` with this `value`. Dangerous, should
+ 183 "Replace the CDR pointer of this `cell` with this `value`. Dangerous, should
- 183 really not exist, but does in Lisp 1.5 (and was important for some
+ 184 really not exist, but does in Lisp 1.5 (and was important for some
- 184 performance hacks in early Lisps)"
+ 185 performance hacks in early Lisps)"
- 185 [^ConsCell cell value]
+ 186 [^ConsCell cell value]
- 186 (if
+ 187 (if
- 187 (instance? ConsCell cell)
+ 188 (instance? ConsCell cell)
- 188 (if
+ 189 (if
-
- 189 (or
+
+ 190 (or
- 190 (instance? ConsCell value)
+ 191 (instance? ConsCell value)
- 191 (number? value)
+ 192 (number? value)
- 192 (symbol? value)
+ 193 (symbol? value)
-
- 193 (= value NIL))
+
+ 194 (= value NIL))
- 194 (try
+ 195 (try
- 195 (.rplacd cell value)
+ 196 (.rplacd cell value)
- 196 cell
+ 197 cell
- 197 (catch Throwable any
+ 198 (catch Throwable any
- 198 (throw (ex-info
+ 199 (throw (ex-info
- 199 (str (.getMessage any) " in RPLACD: `")
+ 200 (str (.getMessage any) " in RPLACD: `")
- 200 {:cause :upstream-error
+ 201 {:cause :upstream-error
- 201 :phase :host
+ 202 :phase :host
- 202 :function :rplacd
+ 203 :function :rplacd
- 203 :args (list cell value)
+ 204 :args (list cell value)
- 204 :type :beowulf}
+ 205 :type :beowulf}
- 205 any))))
+ 206 any))))
+
+
+ 207 (throw (ex-info
+
+
+ 208 (str "Un-ġefōg þing in RPLACD: `" value "` (" (type value) ")")
+
+
+ 209 {:cause :bad-value
+
+
+ 210 :phase :host
+
+
+ 211 :function :rplacd
+
+
+ 212 :args (list cell value)
+
+
+ 213 :type :beowulf})))
+
+
+ 214 (throw (ex-info
+
+
+ 215 (str "Uncynlic miercels in RPLACD: `" cell "` (" (type cell) ")")
+
+
+ 216 {:cause :bad-cell
+
+
+ 217 :phase :host
+
+
+ 218 :detail :rplacd
+
+
+ 219 :args (list cell value)
+
+
+ 220 :type :beowulf}))));; PLUS
+
+
+ 221
+
+
+ 222 (defn LIST
+
+
+ 223 [& args]
- 206 (throw (ex-info
-
-
- 207 (str "Un-ġefōg þing in RPLACD: `" value "` (" (type value) ")")
-
-
- 208 {:cause :bad-value
-
-
- 209 :phase :host
-
-
- 210 :function :rplacd
-
-
- 211 :args (list cell value)
-
-
- 212 :type :beowulf})))
-
-
- 213 (throw (ex-info
-
-
- 214 (str "Uncynlic miercels in RPLACD: `" cell "` (" (type cell) ")")
-
-
- 215 {:cause :bad-cell
-
-
- 216 :phase :host
-
-
- 217 :detail :rplacd
-
-
- 218 :args (list cell value)
-
-
- 219 :type :beowulf}))));; PLUS
+ 224 (make-beowulf-list args))
- 220
+ 225
+
+
+ 226 ;;;; Basic predicates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+ 227
+
+
+ 228 (defmacro NULL
+
+
+ 229 "Returns `T` if and only if the argument `x` is bound to `NIL`; else `F`."
+
+
+ 230 [x]
+
+
+ 231 `(if (= ~x NIL) T F))
+
+
+ 232
+
+
+ 233 (defmacro NILP
+
+
+ 234 "Not part of LISP 1.5: `T` if `o` is `NIL`, else `NIL`."
+
+
+ 235 [x]
+
+
+ 236 `(if (= ~x NIL) T NIL))
+
+
+ 237
- 221 (defn LIST
+ 238 (defn ATOM
- 222 [& args]
-
-
- 223 (make-beowulf-list args))
-
-
- 224
+ 239 "Returns `T` if and only if the argument `x` is bound to an atom; else `F`.
- 225 ;;;; Basic predicates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- 226
-
-
- 227 (defmacro NULL
+ 240 It is not clear to me from the documentation whether `(ATOM 7)` should return
- 228 "Returns `T` if and only if the argument `x` is bound to `NIL`; else `F`."
+ 241 `T` or `F`. I'm going to assume `T`."
- 229 [x]
-
-
- 230 `(if (= ~x NIL) T F))
-
-
- 231
-
-
- 232 (defmacro NILP
-
-
- 233 "Not part of LISP 1.5: `T` if `o` is `NIL`, else `NIL`."
-
-
- 234 [x]
-
-
- 235 `(if (= ~x NIL) T NIL))
-
-
- 236
-
-
- 237 (defn ATOM
-
-
- 238 "Returns `T` if and only if the argument `x` is bound to an atom; else `F`.
-
-
- 239 It is not clear to me from the documentation whether `(ATOM 7)` should return
-
-
- 240 `T` or `F`. I'm going to assume `T`."
-
-
- 241 [x]
+ 242 [x]
- 242 (if (or (symbol? x) (number? x)) T F))
+ 243 (if (or (symbol? x) (number? x)) T F))
- 243
+ 244
- 244 (defmacro ATOM?
+ 245 (defmacro ATOM?
- 245 "The convention of returning `F` from predicates, rather than `NIL`, is going
+ 246 "The convention of returning `F` from predicates, rather than `NIL`, is going
- 246 to tie me in knots. This is a variant of `ATOM` which returns `NIL`
+ 247 to tie me in knots. This is a variant of `ATOM` which returns `NIL`
- 247 on failure."
+ 248 on failure."
- 248 [x]
+ 249 [x]
- 249 `(if (or (symbol? ~x) (number? ~x)) T NIL))
+ 250 `(if (or (symbol? ~x) (number? ~x)) T NIL))
- 250
+ 251
- 251 (defn EQ
+ 252 (defn EQ
- 252 "Returns `T` if and only if both `x` and `y` are bound to the same atom,
+ 253 "Returns `T` if and only if both `x` and `y` are bound to the same atom,
- 253 else `NIL`."
+ 254 else `NIL`."
- 254 [x y]
+ 255 [x y]
- 255 (cond (and (instance? ConsCell x)
+ 256 (cond (and (instance? ConsCell x)
- 256 (.equals x y)) T
+ 257 (.equals x y)) T
- 257 (and (= (ATOM x) T) (= x y)) T
+ 258 (and (= (ATOM x) T) (= x y)) T
- 258 :else NIL))
+ 259 :else NIL))
- 259
+ 260
- 260 (defn EQUAL
+ 261 (defn EQUAL
- 261 "This is a predicate that is true if its two arguments are identical
+ 262 "This is a predicate that is true if its two arguments are identical
- 262 S-expressions, and false if they are different. (The elementary predicate
+ 263 S-expressions, and false if they are different. (The elementary predicate
- 263 `EQ` is defined only for atomic arguments.) The definition of `EQUAL` is
+ 264 `EQ` is defined only for atomic arguments.) The definition of `EQUAL` is
- 264 an example of a conditional expression inside a conditional expression.
+ 265 an example of a conditional expression inside a conditional expression.
- 265
+ 266
- 266 NOTE: returns `F` on failure, not `NIL`"
+ 267 NOTE: returns `F` on failure, not `NIL`"
- 267 [x y]
+ 268 [x y]
- 268 (cond
+ 269 (cond
- 269 (= (ATOM x) T) (if (= x y) T F)
+ 270 (= (ATOM x) T) (if (= x y) T F)
- 270 (= (EQUAL (CAR x) (CAR y)) T) (EQUAL (CDR x) (CDR y))
+ 271 (= (EQUAL (CAR x) (CAR y)) T) (EQUAL (CDR x) (CDR y))
- 271 :else F))
+ 272 :else F))
- 272
+ 273
- 273 (defn AND
+ 274 (defn AND
- 274 "`T` if and only if none of my `args` evaluate to either `F` or `NIL`,
+ 275 "`T` if and only if none of my `args` evaluate to either `F` or `NIL`,
- 275 else `F`.
+ 276 else `F`.
- 276
+ 277
- 277 In `beowulf.host` principally because I don't yet feel confident to define
+ 278 In `beowulf.host` principally because I don't yet feel confident to define
- 278 varargs functions in Lisp."
+ 279 varargs functions in Lisp."
- 279 [& args]
+ 280 [& args]
- 280 ;; (println "AND: " args " type: " (type args) " seq? " (seq? args))
+ 281 ;; (println "AND: " args " type: " (type args) " seq? " (seq? args))
- 281 ;; (println " filtered: " (seq (filter #{F NIL} args)))
+ 282 ;; (println " filtered: " (seq (filter #{F NIL} args)))
-
- 282 (cond (= NIL args) T
+
+ 283 (cond (= NIL args) T
- 283 (seq? args) (if (seq (filter #{F NIL} args)) F T)
+ 284 (seq? args) (if (seq (filter #{F NIL} args)) F T)
-
- 284 :else T))
-
-
- 285
+
+ 285 :else T))
286
-
- 287 (defn OR
-
-
- 288 "`T` if and only if at least one of my `args` evaluates to something other
-
-
- 289 than either `F` or `NIL`, else `F`.
-
-
- 290
-
-
- 291 In `beowulf.host` principally because I don't yet feel confident to define
-
-
- 292 varargs functions in Lisp."
-
-
- 293 [& args]
-
-
- 294 ;; (println "OR: " args " type: " (type args) " seq? " (seq? args))
-
-
- 295 ;; (println " filtered: " (seq (remove #{F NIL} args)))
-
-
- 296 (cond (= NIL args) F
-
-
- 297 (seq? args) (if (seq (remove #{F NIL} args)) T F)
-
-
- 298 :else F))
-
- 299
+ 287
+
+
+ 288 (defn OR
+
+
+ 289 "`T` if and only if at least one of my `args` evaluates to something other
+
+
+ 290 than either `F` or `NIL`, else `F`.
+
+
+ 291
+
+
+ 292 In `beowulf.host` principally because I don't yet feel confident to define
+
+
+ 293 varargs functions in Lisp."
+
+
+ 294 [& args]
+
+
+ 295 ;; (println "OR: " args " type: " (type args) " seq? " (seq? args))
+
+
+ 296 ;; (println " filtered: " (seq (remove #{F NIL} args)))
+
+
+ 297 (cond (= NIL args) F
+
+
+ 298 (seq? args) (if (seq (remove #{F NIL} args)) T F)
+
+
+ 299 :else F))
300
-
- 301 ;;;; Operations on lists ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ 301
- 302 ;;
+ 302 ;;;; Operations on lists ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- 303 ;; TODO: These are candidates for moving to Lisp urgently!
+ 303 ;;
+
+
+ 304 ;; TODO: These are candidates for moving to Lisp urgently!
- 304
+ 305
- 305 (defn ASSOC
+ 306 (defn ASSOC
- 306 "If a is an association list such as the one formed by PAIRLIS in the above
+ 307 "If a is an association list such as the one formed by PAIRLIS in the above
- 307 example, then assoc will produce the first pair whose first term is x. Thus
+ 308 example, then assoc will produce the first pair whose first term is x. Thus
- 308 it is a table searching function.
+ 309 it is a table searching function.
- 309
+ 310
- 310 All args are assumed to be `beowulf.cons-cell/ConsCell` objects.
+ 311 All args are assumed to be `beowulf.cons-cell/ConsCell` objects.
- 311 See page 12 of the Lisp 1.5 Programmers Manual.
+ 312 See page 12 of the Lisp 1.5 Programmers Manual.
- 312
+ 313
- 313 **NOTE THAT** this function is overridden by an implementation in Lisp,
+ 314 **NOTE THAT** this function is overridden by an implementation in Lisp,
- 314 but is currently still present for bootstrapping."
+ 315 but is currently still present for bootstrapping."
- 315 [x a]
+ 316 [x a]
- 316 (cond
+ 317 (cond
- 317 (= NIL a) NIL ;; this clause is not present in the original but is added for
+ 318 (= NIL a) NIL ;; this clause is not present in the original but is added for
- 318 ;; robustness.
+ 319 ;; robustness.
- 319 (= (EQUAL (CAAR a) x) T) (CAR a)
+ 320 (= (EQUAL (CAAR a) x) T) (CAR a)
- 320 :else
+ 321 :else
- 321 (ASSOC x (CDR a))))
+ 322 (ASSOC x (CDR a))))
- 322
+ 323
- 323 (defn PAIRLIS
+ 324 (defn PAIRLIS
- 324 "This function gives the list of pairs of corresponding elements of the
+ 325 "This function gives the list of pairs of corresponding elements of the
- 325 lists `x` and `y`, and APPENDs this to the list `a`. The resultant list
+ 326 lists `x` and `y`, and APPENDs this to the list `a`. The resultant list
- 326 of pairs, which is like a table with two columns, is called an
+ 327 of pairs, which is like a table with two columns, is called an
- 327 association list.
+ 328 association list.
- 328
+ 329
- 329 Eessentially, it builds the environment on the stack, implementing shallow
+ 330 Eessentially, it builds the environment on the stack, implementing shallow
- 330 binding.
+ 331 binding.
- 331
+ 332
- 332 All args are assumed to be `beowulf.cons-cell/ConsCell` objects.
+ 333 All args are assumed to be `beowulf.cons-cell/ConsCell` objects.
- 333 See page 12 of the Lisp 1.5 Programmers Manual.
+ 334 See page 12 of the Lisp 1.5 Programmers Manual.
- 334
+ 335
- 335 **NOTE THAT** this function is overridden by an implementation in Lisp,
+ 336 **NOTE THAT** this function is overridden by an implementation in Lisp,
- 336 but is currently still present for bootstrapping."
+ 337 but is currently still present for bootstrapping."
- 337 [x y a]
+ 338 [x y a]
- 338 (cond
+ 339 (cond
- 339 ;; the original tests only x; testing y as well will be a little more
+ 340 ;; the original tests only x; testing y as well will be a little more
- 340 ;; robust if `x` and `y` are not the same length.
+ 341 ;; robust if `x` and `y` are not the same length.
- 341 (or (= NIL x) (= NIL y)) a
+ 342 (or (= NIL x) (= NIL y)) a
- 342 :else (make-cons-cell
+ 343 :else (make-cons-cell
- 343 (make-cons-cell (CAR x) (CAR y))
+ 344 (make-cons-cell (CAR x) (CAR y))
- 344 (PAIRLIS (CDR x) (CDR y) a))))
+ 345 (PAIRLIS (CDR x) (CDR y) a))))
- 345
+ 346
- 346 ;;;; Arithmetic ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ 347 ;;;; Arithmetic ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- 347 ;;
+ 348 ;;
- 348 ;; TODO: When in strict mode, should we limit arithmetic precision to that
+ 349 ;; TODO: When in strict mode, should we limit arithmetic precision to that
- 349 ;; supported by Lisp 1.5?
+ 350 ;; supported by Lisp 1.5?
- 350
+ 351
- 351 (defn PLUS
+ 352 (defn PLUS
- 352 [& args]
+ 353 [& args]
- 353 (let [s (apply + args)]
+ 354 (let [s (apply + args)]
- 354 (if (integer? s) s (float s))))
+ 355 (if (integer? s) s (float s))))
- 355
+ 356
- 356 (defn TIMES
+ 357 (defn TIMES
- 357 [& args]
+ 358 [& args]
- 358 (let [p (apply * args)]
+ 359 (let [p (apply * args)]
-
- 359 (if (integer? p) p (float p))))
+
+ 360 (if (integer? p) p (float p))))
- 360
+ 361
- 361 (defn DIFFERENCE
+ 362 (defn DIFFERENCE
- 362 [x y]
+ 363 [x y]
- 363 (let [d (- x y)]
+ 364 (let [d (- x y)]
-
- 364 (if (integer? d) d (float d))))
+
+ 365 (if (integer? d) d (float d))))
- 365
+ 366
- 366 (defn QUOTIENT
+ 367 (defn QUOTIENT
- 367 "I'm not certain from the documentation whether Lisp 1.5 `QUOTIENT` returned
+ 368 "I'm not certain from the documentation whether Lisp 1.5 `QUOTIENT` returned
- 368 the integer part of the quotient, or a realnum representing the whole
+ 369 the integer part of the quotient, or a realnum representing the whole
- 369 quotient. I am for now implementing the latter."
+ 370 quotient. I am for now implementing the latter."
- 370 [x y]
+ 371 [x y]
- 371 (let [q (/ x y)]
+ 372 (let [q (/ x y)]
- 372 (if (integer? q) q (float q))))
+ 373 (if (integer? q) q (float q))))
- 373
+ 374
- 374 (defn REMAINDER
+ 375 (defn REMAINDER
- 375 [x y]
+ 376 [x y]
- 376 (rem x y))
+ 377 (rem x y))
- 377
+ 378
- 378 (defn ADD1
+ 379 (defn ADD1
- 379 [x]
+ 380 [x]
- 380 (inc x))
+ 381 (inc x))
- 381
+ 382
- 382 (defn SUB1
+ 383 (defn SUB1
- 383 [x]
-
-
- 384 (dec x))
-
-
- 385
-
-
- 386 (defn FIXP
-
-
- 387 [x]
-
-
- 388 (if (integer? x) T F))
-
-
- 389
-
-
- 390 (defn NUMBERP
-
-
- 391 [x]
-
-
- 392 (if (number? x) T F))
-
-
- 393
-
-
- 394 (defn LESSP
-
-
- 395 [x y]
-
-
- 396 (if (< x y) T F))
-
-
- 397
-
-
- 398 (defn GREATERP
-
-
- 399 [x y]
-
-
- 400 (if (> x y) T F))
-
-
- 401
-
-
- 402 ;;;; Miscellaneous ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- 403
-
-
- 404 (defn GENSYM
-
-
- 405 "Generate a unique symbol."
-
-
- 406 []
-
-
- 407 (symbol (upper-case (str (gensym "SYM")))))
-
-
- 408
-
-
- 409 (defn ERROR
-
-
- 410 "Throw an error"
-
-
- 411 [& args]
-
-
- 412 (throw (ex-info "LISP STÆFLEAHTER" {:args args
-
-
- 413 :phase :eval
-
-
- 414 :function 'ERROR
-
-
- 415 :type :lisp
-
-
- 416 :code (or (first args) 'A1)})))
-
-
- 417
-
-
- 418 ;;;; Assignment and the object list ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- 419
-
-
- 420 (defn OBLIST
-
-
- 421 "Return a list of the symbols currently bound on the object list.
-
-
- 422
-
-
- 423 **NOTE THAT** in the Lisp 1.5 manual, footnote at the bottom of page 69, it implies
-
-
- 424 that an argument can be passed but I'm not sure of the semantics of
-
-
- 425 this."
-
-
- 426 []
-
-
- 427 (if (instance? ConsCell @oblist)
-
-
- 428 (make-beowulf-list (map CAR @oblist))
-
-
- 429 NIL))
-
-
- 430
-
-
- 431 (def magic-marker
-
-
- 432 "The unexplained magic number which marks the start of a property list."
-
-
- 433 (Integer/parseInt "77777" 8))
-
-
- 434
-
-
- 435 (defn hit-or-miss-assoc
-
-
- 436 "Find the position of the binding of this `target` in a Lisp 1.5
-
-
- 437 property list `plist`.
-
-
- 438
-
-
- 439 Lisp 1.5 property lists are not assoc lists, but lists of the form
-
-
- 440 `(name value name value name value...)`. It's therefore necessary to
-
-
- 441 recurse down the list two entries at a time to avoid confusing names
-
-
- 442 with values."
-
-
- 443 [target plist]
-
-
- 444 (if (and (instance? ConsCell plist) (even? (count plist)))
-
-
- 445 (cond (= plist NIL) NIL
-
-
- 446 (= (first plist) target) plist
-
-
- 447 :else (hit-or-miss-assoc target (CDDR plist)))
-
-
- 448 NIL))
-
-
- 449
-
-
- 450 (defn PUT
-
-
- 451 "Put this `value` as the value of the property indicated by this `indicator`
-
-
- 452 of this `symbol`. Return `value` on success.
-
-
- 453
-
-
- 454 NOTE THAT there is no `PUT` defined in the manual, but it would have been
-
-
- 455 easy to have defined it so I don't think this fully counts as an extension."
-
-
- 456 [symbol indicator value]
-
-
- 457 (let [binding (ASSOC symbol @oblist)]
-
-
- 458 (if (instance? ConsCell binding)
-
-
- 459 (let [prop (hit-or-miss-assoc indicator (CDDR binding))]
-
-
- 460 (if (instance? ConsCell prop)
-
-
- 461 (RPLACA (CDR prop) value)
-
-
- 462 (RPLACD binding
-
-
- 463 (make-cons-cell
-
-
- 464 magic-marker
-
-
- 465 (make-cons-cell
-
-
- 466 indicator
-
-
- 467 (make-cons-cell value (CDDR binding)))))))
-
-
- 468 (swap!
-
-
- 469 oblist
-
-
- 470 (fn [ob s p v]
-
-
- 471 (make-cons-cell
-
-
- 472 (make-beowulf-list (list s magic-marker p v))
-
-
- 473 ob))
-
-
- 474 symbol indicator value)))
-
-
- 475 value)
-
-
- 476
-
-
- 477 (defn GET
-
-
- 478 "From the manual:
-
-
- 479
-
-
- 480 '`get` is somewhat like `prop`; however its value is car of the rest of
-
-
- 481 the list if the `indicator` is found, and NIL otherwise.'
-
-
- 482
-
-
- 483 It's clear that `GET` is expected to be defined in terms of `PROP`, but
-
-
- 484 we can't implement `PROP` here because we lack `EVAL`; and we can't have
-
-
- 485 `EVAL` here because both it and `APPLY` depends on `GET`.
-
-
- 486
-
-
- 487 OK, It's worse than that: the statement of the definition of `GET` (and
-
-
- 488 of) `PROP` on page 59 says that the first argument to each must be a list;
-
-
- 489 But the in the definition of `ASSOC` on page 70, when `GET` is called its
-
-
- 490 first argument is always an atom. Since it's `ASSOC` and `EVAL` which I
-
-
- 491 need to make work, I'm going to assume that page 59 is wrong."
-
-
- 492 [symbol indicator]
-
-
- 493 (let [binding (ASSOC symbol @oblist)
-
-
- 494 val (cond
-
-
- 495 (= binding NIL) NIL
-
-
- 496 (= magic-marker
-
-
- 497 (CADR binding)) (loop [b binding]
-
-
- 498 ;; (println "GET loop, seeking " indicator ":")
-
-
- 499 ;; (pretty-print b)
-
-
- 500 (if (instance? ConsCell b)
-
-
- 501 (if (= (CAR b) indicator)
-
-
- 502 (CADR b) ;; <- this is what we should actually be returning
-
-
- 503 (recur (CDR b)))
-
-
- 504 NIL))
-
-
- 505 :else (throw
-
-
- 506 (ex-info "Misformatted property list (missing magic marker)"
-
-
- 507 {:phase :host
-
-
- 508 :function :get
-
-
- 509 :args (list symbol indicator)
-
-
- 510 :type :beowulf})))]
-
-
- 511 ;; (println "<< GET returning: " val)
-
-
- 512 val))
-
-
- 513
-
-
- 514 (defn DEFLIST
-
-
- 515 "For each pair in this association list `a-list`, set the property with this
-
-
- 516 `indicator` of the symbol which is the first element of the pair to the
-
-
- 517 value which is the second element of the pair. See page 58 of the manual."
-
-
- 518 [a-list indicator]
+ 384 [x]
- 519 (doall
-
-
- 520 (map
-
-
- 521 #(when (PUT (CAR %) indicator (CDR %)) (CAR %))
-
-
- 522 a-list)))
+ 385 (dec x))
- 523
+ 386
- 524 (defn DEFINE
+ 387 (defn FIXP
- 525 "Bootstrap-only version of `DEFINE` which, post boostrap, can be overwritten
+ 388 [x]
-
- 526 in LISP.
+
+ 389 (if (integer? x) T F))
- 527
+ 390
+
+
+ 391 (defn NUMBERP
- 528 The single argument to `DEFINE` should be an association list of symbols to
+ 392 [x]
+
+
+ 393 (if (number? x) T F))
+
+
+ 394
+
+
+ 395 (defn LESSP
- 529 lambda functions. See page 58 of the manual."
+ 396 [x y]
+
+
+ 397 (if (< x y) T F))
+
+
+ 398
+
+
+ 399 (defn GREATERP
- 530 [a-list]
+ 400 [x y]
+
+
+ 401 (if (> x y) T F))
+
+
+ 402
+
+
+ 403 ;;;; Miscellaneous ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+ 404
+
+
+ 405 (defn GENSYM
+
+
+ 406 "Generate a unique symbol."
+
+
+ 407 []
+
+
+ 408 (symbol (upper-case (str (gensym "SYM")))))
+
+
+ 409
+
+
+ 410 (defn ERROR
+
+
+ 411 "Throw an error"
+
+
+ 412 [& args]
+
+
+ 413 (throw (ex-info "LISP STÆFLEAHTER" {:args args
+
+
+ 414 :phase :eval
+
+
+ 415 :function 'ERROR
+
+
+ 416 :type :lisp
+
+
+ 417 :code (or (first args) 'A1)})))
+
+
+ 418
+
+
+ 419 ;;;; Assignment and the object list ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+ 420
+
+
+ 421 (defn OBLIST
+
+
+ 422 "Return a list of the symbols currently bound on the object list.
+
+
+ 423
+
+
+ 424 **NOTE THAT** in the Lisp 1.5 manual, footnote at the bottom of page 69, it implies
+
+
+ 425 that an argument can be passed but I'm not sure of the semantics of
+
+
+ 426 this."
+
+
+ 427 []
+
+
+ 428 (if (instance? ConsCell @oblist)
+
+
+ 429 (make-beowulf-list (map CAR @oblist))
+
+
+ 430 NIL))
+
+
+ 431
+
+
+ 432 (def magic-marker
+
+
+ 433 "The unexplained magic number which marks the start of a property list."
+
+
+ 434 (Integer/parseInt "77777" 8))
+
+
+ 435
+
+
+ 436 (defn PUT
+
+
+ 437 "Put this `value` as the value of the property indicated by this `indicator`
+
+
+ 438 of this `symbol`. Return `value` on success.
+
+
+ 439
+
+
+ 440 NOTE THAT there is no `PUT` defined in the manual, but it would have been
+
+
+ 441 easy to have defined it so I don't think this fully counts as an extension."
+
+
+ 442 [symbol indicator value]
+
+
+ 443 (if-let [binding (ASSOC symbol @oblist)]
+
+
+ 444 (if-let [prop (ASSOC indicator (CDDR binding))]
- 531 (DEFLIST a-list 'EXPR))
+ 445 (RPLACD prop value)
+
+
+ 446 (RPLACD binding
+
+
+ 447 (make-cons-cell
+
+
+ 448 magic-marker
+
+
+ 449 (make-cons-cell
+
+
+ 450 indicator
+
+
+ 451 (make-cons-cell value (CDDR binding))))))
+
+
+ 452 (swap!
+
+
+ 453 oblist
+
+
+ 454 (fn [ob s p v]
+
+
+ 455 (make-cons-cell
+
+
+ 456 (make-beowulf-list (list s magic-marker p v))
+
+
+ 457 ob))
+
+
+ 458 symbol indicator value)))
+
+
+ 459
+
+
+ 460 (defn GET
+
+
+ 461 "From the manual:
+
+
+ 462
+
+
+ 463 '`get` is somewhat like `prop`; however its value is car of the rest of
+
+
+ 464 the list if the `indicator` is found, and NIL otherwise.'
+
+
+ 465
+
+
+ 466 It's clear that `GET` is expected to be defined in terms of `PROP`, but
+
+
+ 467 we can't implement `PROP` here because we lack `EVAL`; and we can't have
+
+
+ 468 `EVAL` here because both it and `APPLY` depends on `GET`.
+
+
+ 469
+
+
+ 470 OK, It's worse than that: the statement of the definition of `GET` (and
+
+
+ 471 of) `PROP` on page 59 says that the first argument to each must be a list;
+
+
+ 472 But the in the definition of `ASSOC` on page 70, when `GET` is called its
+
+
+ 473 first argument is always an atom. Since it's `ASSOC` and `EVAL` which I
+
+
+ 474 need to make work, I'm going to assume that page 59 is wrong."
+
+
+ 475 [symbol indicator]
+
+
+ 476 (let [binding (ASSOC symbol @oblist)
+
+
+ 477 val (cond
+
+
+ 478 (= binding NIL) NIL
+
+
+ 479 (= magic-marker
+
+
+ 480 (CADR binding)) (loop [b binding]
+
+
+ 481 ;; (println "GET loop, seeking " indicator ":")
+
+
+ 482 ;; (pretty-print b)
+
+
+ 483 (if (instance? ConsCell b)
+
+
+ 484 (if (= (CAR b) indicator)
+
+
+ 485 (CADR b) ;; <- this is what we should actually be returning
+
+
+ 486 (recur (CDR b)))
+
+
+ 487 NIL))
+
+
+ 488 :else (throw
+
+
+ 489 (ex-info "Misformatted property list (missing magic marker)"
+
+
+ 490 {:phase :host
+
+
+ 491 :function :get
+
+
+ 492 :args (list symbol indicator)
+
+
+ 493 :type :beowulf})))]
+
+
+ 494 ;; (println "<< GET returning: " val)
+
+
+ 495 val))
+
+
+ 496
+
+
+ 497 (defn DEFLIST
+
+
+ 498 "For each pair in this association list `a-list`, set the property with this
+
+
+ 499 `indicator` of the symbol which is the first element of the pair to the
+
+
+ 500 value which is the second element of the pair. See page 58 of the manual."
+
+
+ 501 [a-list indicator]
+
+
+ 502 (map
+
+
+ 503 #(PUT (CAR %) indicator (CDR %))
+
+
+ 504 a-list))
+
+
+ 505
+
+
+ 506 (defn DEFINE
+
+
+ 507 "Bootstrap-only version of `DEFINE` which, post boostrap, can be overwritten
+
+
+ 508 in LISP.
+
+
+ 509
+
+
+ 510 The single argument to `DEFINE` should be an association list of symbols to
+
+
+ 511 lambda functions. See page 58 of the manual."
+
+
+ 512 [a-list]
+
+
+ 513 (DEFLIST a-list 'EXPR))
+
+
+ 514
+
+
+ 515 (defn SET
+
+
+ 516 "Implementation of SET in Clojure. Add to the `oblist` a binding of the
+
+
+ 517 value of `var` to the value of `val`. NOTE WELL: this is not SETQ!"
+
+
+ 518 [symbol val]
+
+
+ 519 (PUT symbol 'APVAL val))
+
+
+ 520
+
+
+ 521 ;;;; TRACE and friends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+ 522
+
+
+ 523 (def traced-symbols
+
+
+ 524 "Symbols currently being traced."
+
+
+ 525 (atom #{}))
+
+
+ 526
+
+
+ 527 (defn traced?
+
+
+ 528 "Return `true` iff `s` is a symbol currently being traced, else `nil`."
+
+
+ 529 [s]
+
+
+ 530 (try (contains? @traced-symbols s)
+
+
+ 531 (catch Throwable _ nil)))
532
- 533 (defn SET
+ 533 (defn TRACE
- 534 "Implementation of SET in Clojure. Add to the `oblist` a binding of the
+ 534 "Add this `s` to the set of symbols currently being traced. If `s`
- 535 value of `var` to the value of `val`. NOTE WELL: this is not SETQ!"
+ 535 is not a symbol or sequence of symbols, does nothing."
- 536 [symbol val]
-
-
- 537 (PUT symbol 'APVAL val))
-
-
- 538
-
-
- 539 ;;;; TRACE and friends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- 540
-
-
- 541 (def traced-symbols
-
-
- 542 "Symbols currently being traced."
-
-
- 543 (atom #{}))
-
-
- 544
-
-
- 545 (defn traced?
-
-
- 546 "Return `true` iff `s` is a symbol currently being traced, else `nil`."
-
-
- 547 [s]
-
-
- 548 (try (contains? @traced-symbols s)
-
-
- 549 (catch Throwable _ nil)))
-
-
- 550
-
-
- 551 (defn TRACE
-
-
- 552 "Add this `s` to the set of symbols currently being traced. If `s`
-
-
- 553 is not a symbol or sequence of symbols, does nothing."
-
-
- 554 [s]
+ 536 [s]
- 555 (swap! traced-symbols
+ 537 (swap! traced-symbols
- 556 #(cond
+ 538 #(cond
- 557 (symbol? s) (conj % s)
+ 539 (symbol? s) (conj % s)
- 558 (and (seq? s) (every? symbol? s)) (union % (set s))
+ 540 (and (seq? s) (every? symbol? s)) (union % (set s))
- 559 :else %)))
+ 541 :else %)))
- 560
+ 542
- 561 (defn UNTRACE
+ 543 (defn UNTRACE
- 562 "Remove this `s` from the set of symbols currently being traced. If `s`
+ 544 "Remove this `s` from the set of symbols currently being traced. If `s`
- 563 is not a symbol or sequence of symbols, does nothing."
+ 545 is not a symbol or sequence of symbols, does nothing."
- 564 [s]
+ 546 [s]
- 565 (cond
+ 547 (cond
- 566 (symbol? s) (swap! traced-symbols #(set (remove (fn [x] (= s x)) %)))
+ 548 (symbol? s) (swap! traced-symbols #(set (remove (fn [x] (= s x)) %)))
- 567 (and (seq? s) (every? symbol? s)) (map UNTRACE s))
+ 549 (and (seq? s) (every? symbol? s)) (map UNTRACE s))
- 568 @traced-symbols)
+ 550 @traced-symbols)
- 569
+ 551
- 570 ;;;; Extensions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ 552 ;;;; Extensions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- 571
+ 553
- 572 (defn DOC
+ 554 (defn DOC
- 573 "Open the page for this `symbol` in the Lisp 1.5 manual, if known, in the
+ 555 "Open the page for this `symbol` in the Lisp 1.5 manual, if known, in the
- 574 default web browser.
+ 556 default web browser.
- 575
+ 557
- 576 **NOTE THAT** this is an extension function, not available in strct mode."
+ 558 **NOTE THAT** this is an extension function, not available in strct mode."
- 577 [symbol]
+ 559 [symbol]
- 578 (when (lax? 'DOC)
+ 560 (when (lax? 'DOC)
- 579 (open-doc symbol)))
+ 561 (open-doc symbol)))
- 580
+ 562
- 581 (defn CONSP
+ 563 (defn CONSP
- 582 "Return `T` if object `o` is a cons cell, else `F`.
+ 564 "Return `T` if object `o` is a cons cell, else `F`.
- 583
+ 565
- 584 **NOTE THAT** this is an extension function, not available in strct mode.
+ 566 **NOTE THAT** this is an extension function, not available in strct mode.
- 585 I believe that Lisp 1.5 did not have any mechanism for testing whether an
+ 567 I believe that Lisp 1.5 did not have any mechanism for testing whether an
- 586 argument was, or was not, a cons cell."
+ 568 argument was, or was not, a cons cell."
- 587 [o]
+ 569 [o]
- 588 (when (lax? 'CONSP)
+ 570 (when (lax? 'CONSP)
- 589 (if (instance? ConsCell o) 'T 'F)))
+ 571 (if (instance? ConsCell o) 'T 'F)))