beowulf.bootstrap

Lisp as defined in Chapter 1 (pages 1-14) of the Lisp 1.5 Programmer's Manual; that is to say, a very simple Lisp language, which should, I believe, be sufficient in conjunction with the functions provided by beowulf.host, be sufficient to bootstrap the full Lisp 1.5 interpreter..

The convention is adopted that functions in this file with names in ALLUPPERCASE are Lisp 1.5 functions (although written in Clojure) and that therefore all arguments must be numbers, symbols or beowulf.cons_cell.ConsCell objects.

APPLY

(APPLY function args environment depth)

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.

EVAL

(EVAL expr)(EVAL expr env depth)

Evaluate this expr and return the result. If environment is not passed, it defaults to the current value of the global object list. The depth argument is part of the tracing system and should not be set by user code.

All args are assumed to be numbers, symbols or beowulf.cons-cell/ConsCell objects. However, if called with just a single arg, expr, I’ll assume it’s being called from the Clojure REPL and will coerce the expr to ConsCell.

find-target

TODO: write docs

PROG

(PROG program env depth)

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 tp 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 PROGs 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 A3except 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-eval

(prog-eval expr vars env depth)

Like EVAL, q.v., except handling symbols, and expressions starting GO, RETURN, SET and SETQ specially.

try-resolve-subroutine

(try-resolve-subroutine subr args)

Attempt to resolve this subr with these arg.