All ready to implement property lists, not yet done.

This commit is contained in:
Simon Brooke 2023-04-02 03:45:40 +01:00
parent 5ee9531e6b
commit b61e7c3e8c
16 changed files with 225 additions and 125 deletions

View file

@ -14,7 +14,7 @@
(ASSOC LAMBDA (X L)
(COND
((NULL L) (QUOTE NIL))
((AND (CONSP (CAR L)) (EQ (CAAR L) X)) (CDAR L))
((AND (CONSP (CAR L)) (EQ (CAAR L) X)) (CAR L))
((QUOTE T) (ASSOC X (CDR L)))))
(ATOM)
(CAR)
@ -110,6 +110,10 @@
((NULL X) (ERROR (QUOTE F2)))
((NULL Y) (ERROR (QUOTE F3)))
(T (CONS (CONS (CAR X) (CAR Y)) (PAIR (CDR X) (CDR Y))))))
(PAIRLIS LAMBDA (X Y A)
(COND
((NULL X) A)
((QUOTE T) (CONS (CONS (CAR X) (CAR Y)) (PAIRLIS (CDR X) (CDR Y) A)))))
(PLUS)
(PRETTY)
(PRINT)
@ -118,6 +122,7 @@
(X Y U)
(COND
((NULL X) (U)) ((EQ (CAR X) Y) (CDR X)) ((QUOTE T) (PROP (CDR X) Y U))))
(QUOTE LAMBDA (X) X)
(QUOTIENT)
(RANGE LAMBDA (N M) (COND ((LESSP M N) (QUOTE NIL)) ((QUOTE T) (CONS N (RANGE (ADD1 N) M)))))
(READ)
@ -128,5 +133,16 @@
(RPLACD)
(SET)
(SUB1 LAMBDA (N) (DIFFERENCE N 1))
(SUB2 LAMBDA (A Z)
(COND
((NULL A) Z)
((EQ (CAAR A) Z) (CDAR A))
((QUOTE T) (SUB2 (CDAR A) Z))))
(SUBLIS LAMBDA (A Y) (COND ((ATOM Y) (SUB2 A Y)) ((QUOTE T) (CONS))))
(SUBST LAMBDA (X Y Z)
(COND
((EQUAL Y Z) X)
((ATOM Z) Z)
((QUOTE T) (CONS (SUBST X Y (CAR Z)) (SUBST X Y (CDR Z))))))
(SYSIN)
(SYSOUT) (TERPRI) (TIMES) (TRACE) (UNTRACE) (ZEROP LAMBDA (N) (EQ N 0)))

View file

@ -1,21 +0,0 @@
;; see page 70 of Lisp 1.5 Programmers Manual; this expands somewhat
;; on the accounts of eval and apply given on page 13. This is M-expr
;; syntax, obviously.
;; apply
;; NOTE THAT I suspect there is a typo in the printed manual in line
;; 7 of this definition, namely a missing closing square bracket before
;; the final semi-colon; that has been corrected here.
apply[fn;args;a] = [
null[fn] -> NIL;
atom[fn] -> [get[fn;EXPR] -> apply[expr; args; a];
get[fn;SUBR] -> {spread[args];
$ALIST := a;
TSX subr4, 4};
T -> apply[cdr[sassoc[fn; a; λ[[]; error[A2]]]]; args a]];
eq[car[fn]; LABEL] -> apply[caddr[fn]; args;
cons[cons[cadr[fn];caddr[fn]]; a]];
eq[car[fn]; FUNARG] -> apply[cadr[fn]; args; caddr[fn]];
eq[car[fn]; LAMBDA] -> eval[caddr[fn]; nconc[pair[cadr[fn]; args]; a]];
T -> apply[eval[fn;a]; args; a]]

View file

@ -0,0 +1,40 @@
;; see page 70 of Lisp 1.5 Programmers Manual; this expands somewhat
;; on the accounts of eval and apply given on page 13. This is M-expr
;; syntax, obviously.
;; ## APPLY
;; NOTE THAT I suspect there is a typo in the printed manual in line
;; 7 of this definition, namely a missing closing square bracket before
;; the final semi-colon; that has been corrected here.
;; RIGHT! So the 'EXPR' representation of a function is expected to be
;; on the `EXPR` property on the property list of the symbol which is
;; its name; an expression is simply a Lisp S-Expression as a structure
;; of cons cells and atoms in memory. The 'SUBR' representation, expected
;; to be on the `SUBR` property, is literally a subroutine written in
;; assembly code, so what is happening in the curly braces is putting the
;; arguments into processor registers prior to a jump to subroutine - TSX
;; being presumably equivalent to a 6502's JSR call.
;; This accounts for the difference between this statement and the version
;; on page 12: that is a pure interpreter, which can only call those host
;; functions that are explicitly hard coded in.
;; This version knows how to recognise subroutines and jump to them, but I
;; think that by implication at least this version can only work if it is
;; itself compiled with the Lisp compiler, since the section in curly braces
;; appears to be intended to be passed to the Lisp assembler.
;; apply[fn;args;a] = [
;; null[fn] -> NIL;
;; atom[fn] -> [get[fn;EXPR] -> apply[expr; args; a];
;; get[fn;SUBR] -> {spread[args];
;; $ALIST := a;
;; TSX subr4, 4};
;; T -> apply[cdr[sassoc[fn; a; λ[[]; error[A2]]]]; args a]];
;; eq[car[fn]; LABEL] -> apply[caddr[fn]; args;
;; cons[cons[cadr[fn];caddr[fn]]; a]];
;; eq[car[fn]; FUNARG] -> apply[cadr[fn]; args; caddr[fn]];
;; eq[car[fn]; LAMBDA] -> eval[caddr[fn]; nconc[pair[cadr[fn]; args]; a]];
;; T -> apply[eval[fn;a]; args; a]]

View file

@ -1,7 +1,22 @@
;; Not present in Lisp 1.5(!)
;; Page 12 of the manual; this does NOT do what I expect a modern
;; ASSOC to do!
;; Modern ASSOC would be:
;; assoc[x; l] = [null[l] -> NIL;
;; and[consp[car[l]]; eq[caar[l]; x]] -> cdar[l];
;; T -> assoc[x; cdr[l]]]
;; In the Lisp 1.5 statement of ASSOC, there's no account of what should happen
;; if the key (here `x`) is not present on the association list `a`. It seems
;; inevitable that this causes an infinite run up the stack until it fails with
;; stack exhaustion. Consequently this may be right but I'm not implementing it!
;; assoc[x; a] = [equal[caar[a]; x] -> car[a];
;; T -> assoc[x; cdr[a]]]
;; Consequently, my solution is a hybrid. It returns the pair from the
;; association list, as the original does, but it traps the end of list
;; condition, as a modern solution would.
assoc[x; l] = [null[l] -> NIL;
and[consp[car[l]]; eq[caar[l]; x]] -> cdar[l];
and[consp[car[l]]; eq[caar[l]; x]] -> car[l];
T -> assoc[x; cdr[l]]]
;; (ASSOC 'C (PAIR '(A B C D E F) (RANGE 1 6)))

View file

@ -0,0 +1,5 @@
;; page 12
pairlis[x;y;a] = [null[x] -> a;
T -> cons[cons[car[x]; car[y]];
pairlis[cdr[x]; cdr[y]; a]]]

View file

@ -0,0 +1,10 @@
;; There are two different statements of SUBLIS and SUB2 in the manual, on
;; pages 12 and 61 respectively, although they are said to be semantically
;; equivalent; this is the version from page 12.
sub2[a; z] = [null[a] -> z;
eq[caar[a]; z] -> cdar[a];
T -> sub2[cdar[a]; z]]
sublis[a; y] = [atom[y] -> sub2[a; y];
T -> cons[]]

View file

@ -0,0 +1,5 @@
;; page 11
subst[x; y; z] = [equal[y; z] -> x;
atom[z] -> z;
T -> cons[subst[x; y; car[z]]; subst[x; y; cdr[z]]]]